Python中的代理模式
我在代码里实现了很多类。现在我意识到,对于这些类中每个被调用的方法,我都需要添加一行代码:
with service as object:
所以我想用代理模式来自动完成这个工作,这是我的示例代码:
class A(object):
def __init__(self, name):
self.name = name
def hello(self):
print 'hello %s!' % (self.name)
def __enter__(self):
print 'Enter the function'
return self
def __exit__(self, exc_type, exc_value, traceback):
print 'Exit the function'
class Proxy(object):
def __init__(self, object_a):
# object.__setattr__(self, '_object_a', object_a)
self._object_a = object_a
def __getattribute__(self, name):
service = object.__getattribute__(self, '_object_a')
with service as service:
result = getattr(service, name)
return result
if __name__=='__main__':
a1 = A('A1')
b = Proxy(a1)
b.hello()
a2 = A('A2')
b = Proxy(a2)
b.hello()
一切都正常,我得到了输出:
Enter the function A1
Exit the function A1
hello A1!
Enter the function A2
Exit the function A2
hello A2!
但这并不是我真正需要的,因为我需要的是等价于:
with a1 as a1:
a1.hello()
而且我必须得到这个输出:
Enter the function A1
hello A1!
Exit the function A1
Enter the function A2
hello A2!
Exit the function A2
我需要怎么做才能得到这个结果?谢谢
2 个回答
0
你在你的 __enter__
方法里缺少一个返回语句,这个返回语句应该返回你这个类的实例,也就是 self
。
关于这个问题,在你的 Proxy
里,结果可能是在上下文关闭后才被计算的。你可以试试这个,看看你实际上返回的是什么——是一个绑定的方法:
def __getattribute__(self, name):
service = object.__getattribute__(self, '_object_a')
with service as service:
result = getattr(service, name)
print result
return result
这样会显示
Enter the function
<bound method A.hello of <__main__.A object at 0x022A2950>>
Exit the function
然后方法才会被调用,等到 __getattribute__
返回了它之后。
8
我会使用一个装饰器:
class Proxy(object):
def __init__(self, object_a):
self._object_a = object_a
def decorateEnterExit(self, obj, f):
def inner(*args, **kwargs):
with obj as _:
return f(*args, **kwargs)
return inner
def __getattribute__(self, name):
obj = object.__getattribute__(self, '_object_a')
dee = object.__getattribute__(self, 'decorateEnterExit')
return dee(obj, getattr(obj, name))
这样的话,只有在函数被执行的时候,with语句才会被计算。你之前的做法是,with语句会先被计算(包括退出它),然后才会返回这个函数以供调用。现在我们返回的是一个函数,这个函数会自己进入with语句,并在里面调用那个函数。
>>> Proxy(A('Ax')).hello()
Enter the function
hello Ax!
Exit the function
注意,你需要在的__enter__
方法中返回self
:
def __enter__(self):
print 'Enter the function'
return self