我有一个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()
我该怎么做才能改变这个?
答案 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的实例。它取决于你想用这个代理实现的目标。