正确的语法是什么?
class Foo:
def hello(self):
print "Hello cruel world!"
def greet_first(self, f):
self.hello()
return lambda *args, **kwargs: f(*args, **kwargs)
@greet_first
def goodbye(self, concat):
print "Goodbye {0}".format(concat)
if __name__=='__main__':
bar = Foo()
bar.goodbye(' and thanks for all the fish')
Traceback (most recent call last):
File "prog.py", line 1, in <module>
class Foo:
File "prog.py", line 9, in Foo
@greet_first
TypeError: greet_first() takes exactly 2 arguments (1 given)
答案 0 :(得分:2)
立即调用装饰器,它不被视为Foo
的方法,而是被视为本地函数。 @greet_first
语法实际上意味着:
goodbye = greet_first(goodbye)
并立即执行 。 不是绑定方法,因此不包括self
参数。将greet_first
作为方法是没有意义的。将其移出并完全删除self
参数。
您需要调整装饰器以返回可调用来替换goodbye
:
def greet_first(f):
def wrapper(self, *args, **kwargs):
self.hello()
return f(self, *args, **kwargs)
return wrapper
这样每次调用self.hello()
时都会调用goodbye
。
如果 让greet_first
成为Foo
的一部分,可以使用@staticmethod
装饰,但你必须跳通过额外的箍只是为了能够将它用于其他方法声明;你必须将它视为它已成为的描述符并在其上调用.__get__()
:
class Foo(object):
def hello(self):
print "Hello cruel world!"
@staticmethod
def greet_first(f):
def wrapper(self, *args, **kwargs):
self.hello()
return f(self, *args, **kwargs)
return wrapper
@greet_first.__get__(object)
def goodbye(self, concat):
print "Goodbye {0}".format(concat)
我使用任意类型调用.__get__()
(在这种情况下为object
),因为staticmethod
无论如何都忽略该参数;我们不能在这里使用Foo
,因为该类在其定义的代码内部尚未最终确定。
请注意,要使@staticmethod
完全正常工作,您需要在Python 2中继承object
。