Python中的装饰器、lambda和成员函数调用?
正确的语法是什么?
编程尝试
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)
参考资料
1 个回答
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
这样每次调用goodbye
的时候,self.hello()
都会被调用。
如果你必须把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)
我用一个任意的类型(在这个例子中是object
)来调用.__get__()
,因为staticmethod
反正会忽略那个参数;我们不能在这里使用Foo
,因为在它的定义代码中,这个类还没有被最终确定。
注意,在Python 2中,要让@staticmethod
正常工作,你需要从object
继承。