[英]python class decorator inside method
我尝试将装饰器模式用于类层次结构,因此我如下定义了类装饰器:
def delegate(cls, target='_base'):
class Wrapper(object):
def __init__(self, *args, **kwargs):
self.wrapped = cls(*args, **kwargs)
def __getattr__(self, name):
if hasattr(self.wrapped, name):
return getattr(self.wrapped, name)
else:
return getattr(self.wrapped.__dict__.get(target), name)
return Wrapper
class A(object):
def __init__(self):
pass
def foo(self):
print('this is foo()')
@delegate
class B(object):
def __init__(self):
self._base = A()
def bar(self):
self.foo() # self._base.foo() will work
def main():
B().foo() #1. works
B().bar() #2. attribute not found error
为什么在#1起作用时,对bar()中的self.foo()的调用没有抛出委托? 为了用没有硬性代码self._base.foo()的装饰器解决它,我是否必须为B中需要_base的每个方法编写方法装饰器? 我尝试减少样板代码。
def delegate(cls, target='_base'):
class Wrapper(object):
def __init__(self, *args, **kwargs):
self.wrapped = cls(*args, **kwargs)
def __getattr__(self, name):
if hasattr(self.wrapped, name):
return getattr(self.wrapped, name)
else:
return getattr(self.wrapped.__dict__.get(target), name)
return Wrapper
class A(object):
def __init__(self):
pass
def foo(self):
print('this is foo()')
@delegate
class B(object):
def __init__(self):
self._base = A()
def bar(self):
self.foo()
def thirdbar(self):
self._base.foo() # self._base.foo() will work
def secondbar(self,x):
x.foo() # self._base.foo() will work
x=B()
x.foo() #1. works
x.secondbar(x) #it is working
x.thirdbar() #it is working
x.bar() #still not working
之所以发生这种情况,是因为装饰器的行为(至少对我而言)有点违反直觉。
当您检查所有涉及的对象的类型时,将发生以下情况:
>>> type(b)
<class 'Wrapper'>
>>> type(b.wrapped)
<class 'B'>
>>> type(b.wrapped._base)
<class 'A'>
因为b
实际上是Wrapper
的实例,而不是 B
,所以当您调用b.foo()
,发生的是(psuedocode):
b.foo() --> Wrapper.__getattr__(foo) --> wrapped._base.foo
因此foo
来自Wrapper
对象的__getattr__
而不是Bar
对象的。
问题在于以这种方式定义bar
:
def bar(self):
self.foo()
self
不引用Wrapper
对象的foo
属性,而是Bar
对象的foo属性,该属性不存在。
因此,当您调用b.bar()
,方法链为:
b.bar() --> Wrapper.__getattr__(bar) --> wrapped.bar() --> wrapped.foo()
您可以通过让Bar
调用self._base.foo()
来解决此问题。
B().bar() #2. attribute not found error
为什么? 实例化Wrapper
该实例的wrapped
。
然后,您可以对'bar'
进行点分查找。
'bar'
将在包装好的B
找到,因此这将返回一个绑定方法, self
就是包装的B()
,而不是Wrapper()
:
def __getattr__(self, name):
if hasattr(self.wrapped, name):
return getattr(self.wrapped, name)
我不确定您要在这里完成什么。 似乎将子类化或直接将行为添加到类中可能比这样做更好。
据说调试代码的技巧必须是编写代码的两倍。 如果您太聪明了,那么就使您无法调试它。 我建议在这里做些不同的事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.