在Python中代理变量

时间:2015-02-10 04:39:44

标签: python class proxy

我有一个Python对象,我希望屏蔽任何内部和外部访问,并通过代理运行每个请求。到目前为止,我使用了this段代码。我将它子类化并使用我想要代理的对象初始化它。

不幸的是,它没有涵盖代理对象内发生访问的情况。

class A(object):
    def do_something(self):
       self.foo.perform_action()

class MyProxy(Proxy):    
    def __init__(self, obj):
        super(MyProxy, self).__init__(obj)
        self.proxy_foo = ProxyFoo(obj.foo)

    def __getattribute__(self, item):
        if item == 'foo':
           return self.proxy_foo
        return super(MyProxy, self).__getattribute__(item)

a = A()
myproxy = Proxy(a)
# do_something should work on proxy_foo, but it operates on a.foo
myproxy.do_something()

我该怎么做才能改变这个?

1 个答案:

答案 0 :(得分:0)

我认为这不是一个好主意。我能想到的唯一方法是捕获do_something的访问权限并返回带有不同self对象的已修改绑定方法。这最多会让人感到困惑,最糟糕的是,因为这意味着当A试图访问自己时,它实际上并不是访问自己,而是代理。您可以使用当前的代理类执行此操作,但必须拦截对do_something的访问权限,而不是foo

class MyProxy(Proxy):    
    def __init__(self, obj):
        super(MyProxy, self).__init__(obj)
        self.proxy_foo = 999

    def __getattribute__(self, item):
        #print("__getattribute__({}, {})".format(self, item))
        if item == 'foo':
            return self.proxy_foo
        if item == 'do_something':
            return functools.partial(object.__getattribute__(self, '_obj').__class__.do_something, self)
        return super(MyProxy, self).__getattribute__(item)

a = A()
myproxy = MyProxy(a)

然后:

>>> myproxy.do_something()
999

这只能起作用,因为Proxy类甚至代理__class__属性,导致代理伪装成代理类的实例。即便如此,这意味着myproxy.do_something()会导致对__getattribute__的四次单独调用,因为您可以看到是否取消注释该打印(一个获取do_something,内部生成的__class__查找1}},一个获得foo,另一个获得proxy_foo)。您可以看到,如果您调用的方法实际上对任何属性执行了任何操作,则调用次数可能会快速增长。此外,我不清楚它甚至适用于所有情况(例如,classmethods,双下划线私有类级变量)。甚至可能会出现拐点情况,它会进入一个无限循环。

通常,代理意味着提供一种方法,在一个使用该对象的封闭操作中将一个对象替换为另一个对象。试图欺骗一个物体相信它本身是另一个对象是一个冒险的命题。你可能最好做一个mixin代理类,它有自己的__getattribute__做你想要的代理,然后创建一个子类,将它与A混合并使用它的实例而不是A的实例。它取决于你想用这个代理实现的目标。