是否可以在python中装饰像__getattr__
这样的方法?
喜欢这个
@myWrapper
def __getattr__(self,attrName):
'''
myCode Goes here
'''
当我尝试使用上述内容时,我遇到了一些错误:
感谢willem指出..
我发现了我在代码中犯的错误。
我打算做这样的事情
class A:
def __init__(self):
self.a=someObject()
@mywrapper
def __getattr__(self,argName):
# call self.a 's method. If that doesnt have
# then raise an exception
所以我的方法可能有一些参数,我也需要传递它..
所以我写了这样的东西来测试:
class A:
def __init__(self):
self.a=someObject()
@mywrapper
def __getattr__(self,argName):
print('getAttr called for {}'.format(argName))
def mymethod(*args,**kwargs):
import ipdb;ipdb.set_trace()
return mymethod
我的包装器代码如下所示:
def mywrapper(method):
def methodWrapper(obj,name):
print("In decorator for {}".format(method));
method(obj,name)
return methodWrapper
但是当我像obj.c(1)一样执行时,我得到以下异常
TypeError: 'NoneType' object is not callable
事实上,装饰器和__getattr__
中的print语句都已执行但我看到异常..
如何解决这个问题?
答案 0 :(得分:3)
是的,这是可能的。 __getattr__
实际上只是另一个函数,尽管Python解释器会将其称为回退机制之一。关于__init__
,__getattr__
等没有任何固有的特殊内容。
按照惯例,带有前导和尾部双下划线的名称是“magic”对象或属于用户控制的命名空间的属性。例如。 __init__
,__import__
或__file__
。不要发明这样的名字;只能按照记录的方式使用它们。“。但这是风格指南(你最好遵循)。
出于某种原因,您的@myWrapper
不尊重(数量)属性。
例如,如果您要写一个包装器:
def myWrapper(func):
def g(self,attrName):
return func(self,'foo_%s'%attrName)
return g
然后有没有问题。
如果我们现在定义一个类Foo
:
class Foo:
@myWrapper
def __getattr__(self,attrName):
print(attrName)
然后我们看到装饰器正常工作:
>>> foo = Foo()
>>> foo.bla
foo_bla
正如您所见,__getattr__
打印foo_bla
,这意味着myWrapper
已将该属性添加到foo_
之前。
至于你的(编辑过的)问题,我想它之所以说“TypeError:'NoneType'对象不可调用”是因为装饰者应返回一个(新)函数强>
可能你的装饰师看起来像:
def mywrapper(func):
def g(self,attrName):
return func(self,attrName)
所以你可能忘了拨打return g
。
编辑:根据您更新的问题,问题是您不返回内部__getattr__
电话的结果:
def mywrapper(method):
def methodWrapper(obj,name):
print("In decorator for {}".format(method));
return method(obj,name) -- with a return statement
return methodWrapper
这很重要,因为__getattr__
会返回一个函数。请注意,在mywrapper
的上下文中,method
是原始 __getattr__
,methodWrapper
是新__getattr__
。所以你应该传递原始__getattr__
的结果。现在你不用它做任何事情并返回(默认情况下)None
。