2017-02-21 94 views
4

考虑下面的代码:类继承

class A(object): 
    a = [] 

    @classmethod 
    def eat(cls, func): 
     print "called", func 
     cls.a.append(func) 


class B(A): 
    @A.eat 
    def apple(self, x): 
     print x 

    A.eat(lambda x: x + 1) 


print A.a 

输出: called <function apple at 0x1048fba28> called <function <lambda> at 0x1048fbaa0> [<function apple at 0x1048fba28>, <function <lambda> at 0x1048fbaa0>]

我预计A.a是空的,因为我们还没有创建object.How在这里得到补充2功能究竟是什么导致eat被称为2次?

+2

加载类时执行类中的所有语句,例如, 'class A:print('hello')'会在加载类时打印“hello”。当类加载时,'@ A.eat'和'A.eat()'都是执行语句,即使没有'print A.a',也会得到前2个打印输出。 – AChampion

回答

5

因为class definition is an executable statement

类的主体内部(但函数定义之外)的任何代码都将在运行时执行。

如果您想让代码只在实例化类对象时才运行,请将其放入__init__类方法中。

注意some tutorials犯了这个错误,这无疑增加了混乱:

当你定义一个类无代码运行 - 你只是做 函数和变量。

这是完全错误的。

5

在导入模块时执行类体定义。

这也意味着修饰器也被执行,将apple函数对象传递给A.eat,然后将返回值绑定到您传递的函数的名称(apple)。

你可以阅读更多关于Python的执行模型在这里:https://docs.python.org/2/reference/executionmodel.html