Python递归代理

Python递归代理,python,object,proxy,Python,Object,Proxy,希望这能解释我想要达到的目标 class A(object): def hello(self): print "hello" a = A() a.b = A() a.b.c = A() a.b.d = [] a.b.d.append(A()) p = Proxy(a) print p.b "b accessed" <__main__.A object at 0xb73f3bec> print p.b.c "b accessed" "c accesse

希望这能解释我想要达到的目标

class A(object):
    def hello(self):
        print "hello"

a = A()
a.b = A()
a.b.c = A()
a.b.d = []
a.b.d.append(A())


p = Proxy(a)

print p.b
"b accessed"
<__main__.A object at 0xb73f3bec>

print p.b.c
"b accessed"
"c accessed"
<__main__.A object at 0xb73f3dec>

print p.b.d
"b accessed"
"d accessed"
[<__main__.A object at 0xb73f3bcc>]

print p.b.d[0]
"b accessed"
"d accessed"
<__main__.A object at 0xb73e766c>

print p.b.d[0].hello()
"b accessed"
"d accessed"
"hello called"
"hello"
A类(对象):
def你好(self):
打印“你好”
a=a()
a、 b=a()
a、 b.c=a()
a、 b.d=[]
a、 b.d.append(a())
p=代理(a)
印刷品
“b访问”
印刷品
“b访问”
“c访问”
打印p.b.d
“b访问”
“d已访问”
[]
打印p.b.d[0]
“b访问”
“d已访问”
打印p.b.d[0].hello()
“b访问”
“d已访问”
“你好,打电话来”
“你好”
基本上,只要我沿着一个结构走下去,它就会不断返回代理对象。最好只在第一次访问属性并存储在“父对象”上时创建这些代理对象。这样做的目的是,在对(嵌套)对象调用任何方法之前,我可以执行一些逻辑

我看了一下:
但是它只做第一层,我看不出如何操作它来满足我的需要。

使用全局缓存,并创建一个代理工厂方法,在创建新代理之前首先检查全局缓存

请注意,此解决方案不在“父”上存储子代理对象。相反,它使用
id(obj)
技巧从缓存中检索对象,不管对象有多深

NOT_FOUND = object()

# global proxy cache
_id2obj_dict = {}

def remember(oid, proxy):
    _id2obj_dict[oid] = proxy
    return oid

def id2obj(oid):
    print("accessing cahed object")
    return _id2obj_dict[oid]

class A(object):
    def hello(self):
        print "hello"

class Proxy(object):
    @classmethod
    def create(cls, obj):
        ''' object factory '''
        oid = id(obj)
        if oid in _id2obj_dict:
            return id2obj(oid)
        proxy = cls()
        proxy.obj = obj
        remember(oid, proxy)
        return proxy
    def __getattr__(self, attr):
        prop = getattr(self.obj, attr, NOT_FOUND)
        if prop is NOT_FOUND:
            raise AttributeError()
        print("{} accessed".format(attr))
        proxy = Proxy.create(prop)
        return proxy
    def __getitem__(self, index):
        prop = self.obj.__getitem__(index)
        proxy = Proxy.create(prop)
        return proxy
    def __call__(self):
        print("{} called".format(self.obj.__name__))
        return self.obj()



a = A()
a.b = A()
a.b.c = A()
a.b.d = []
a.b.d.append(A())


p = Proxy.create(a)

<> P>有一些选择要考虑递归代理,有不同的权衡:

  • 重写类

    可能是最好、最容易实现的选项。制作一个用代理类替换类的装饰器。您可以使代理更智能一些,以便在实例上设置代理行为标志之前,该类的行为与普通类类似

    例如:

    @ProxyWhenFlag(“打开代理”)
    A类:
    def你好(self):
    打印“你好”
    a=a()
    a、 b=a()
    a、 b.c=a()
    a、 b.d=[]
    a、 b.d.append(a())
    
    用法:

    >>> a.b
    <__main__.A object at 0xb73f3bec>
    >>> a.__turn_on_proxy__ = True
    >>> a.b
    "b accessed"
    <__main__.A object at 0xb73f3bec>
    
    >>a.b
    >>>a.。\uuuu打开\u代理\uuuuu=True
    >>>a.b
    “b访问”
    
  • 修改实例

    您可以通过覆盖
    \uuu getattribute\uuu
    来拦截对象的大多数属性访问

    一个简单的方法是为您的代理创建一个
    imprint
    方法,该方法将删除所有其他方法,并且只允许通过代理方法访问底层对象

    注意
    \uuuuu
    基本方法必须单独重写(它们不会被
    \uuuuu getattribute\uuuu
    拦截)<代码>元组、具有
    插槽的对象
    和数据结构(
    列表
    Dict
    等)都进行了优化,
    \uuuu getattribute\uuuu
    也不会在那里工作

    更复杂的方法是将对象标记为代理,并通过覆盖
    对象
    元组
    列表
    Dict
    设置
    等来检查标记,从而处理代理。您可以使用
    bankedenfruit
    模块覆盖内置方法。做这件事要特别小心。它非常重要,会影响整个应用程序的性能。不过,如果您要代理几乎所有内容(程序分析/跟踪/AOP框架等),那么它仍然是值得的

  • 使用全局缓存

    正如姆巴西指出的那样,这可能是最具成本效益的选择。但是,如果您想将代理注入到其他代码中,您仍然需要使用代理对象获取其他代码