Python中的装饰器,lambda和成员函数调用?

时间:2013-02-09 13:09:05

标签: python methods decorator self python-decorators

正确的语法是什么?

编程尝试

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)

参考

Click to run the code (IDEone)

1 个答案:

答案 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