Python在类中初始化列表

时间:2018-02-28 23:48:58

标签: python class

我不理解python的行为,我有很多相同的错误:

  

文件" ./ start.py",第20行,在print2中      item.print2()
  RuntimeError:超出最大递归深度

我的代码如下:

self.items = []

当我在构造函数(__init__)中添加{{1}}时,它可以正常工作。你能解释一下这种行为吗?

3 个答案:

答案 0 :(得分:4)

items是一个类变量,因此它由Composite的每个实例共享。当您append进入items时,所有实例都会获得该项目。因此,在添加leaf后,您有:

   Type                    Composite.items
------------------------------------------
 Composite    category1    [leaf1, leaf2]
                  |
 Composite      leaf1      [leaf1, leaf2]
                  |
      Leaf      leaf2

如果在print2上调用leaf1,它会尝试在课程中的每个print2上调用items,其中包括leaf1,再次,在一次无限的递归中。

如果您在self.items = []内初始化__init__,它将是一个实例变量而不是类变量,因此每个Composite都有自己的items列表。

答案 1 :(得分:4)

因为所有对象都是共享项目...这是一个类变量,即"静态"

class Foo:
    # <anything assigned here is static>
    static_var1 = 'foo'
    def some_method(self, bar):
        self.x = bar # this is an *instance* variable

所以:

def print2(self):
    if self.items:
        for item in self.items:
            item.print2()

迭代静态items。注意:

In [11]: category.items
Out[11]: [<__main__.Composite at 0x103078978>, <__main__.Leaf at 0x103078ac8>]

In [12]: category.items[0].name
Out[12]: 'leaf1'

当您点击第一个项目时,它会调用item.print2(),然后开始迭代items,然后再次点击'leaf1'再次调用{ {1}} ...

注意,Python的对象模型非常简单,item.print2()相当于instance.method(),即唯一的#34;魔法&#34;在方法中发生的是,如果通过实例访问方法,实际返回的是绑定方法,它将实例绑定为函数的第一个参数。所以请注意:

InstanceClass.method(instance)

注意,In [15]: class Foo: ...: def mutate(self, x): ...: self.foo = x ...: In [16]: f = Foo() In [17]: f.mutate(42) In [18]: f.foo Out[18]: 42 In [19]: Foo.mutate(f, 99) In [20]: f.foo Out[20]: 99 只是一个功能。它并不关心Foo.mutate实际上是什么:

self

一点点奥秘,每次访问一个方法,都会创建一个全新的绑定方法对象:

In [21]: class Bar:
    ...:     pass
    ...:

In [22]: b = Bar()

In [23]: Foo.mutate(b, 'foooooo')

In [24]: b.foo
Out[24]: 'foooooo'

这导致了看似奇怪的事情:

In [34]: f.mutate
Out[34]: <bound method Foo.mutate of <__main__.Foo object at 0x1030641d0>>

In [35]: methods = f.mutate, f.mutate, f.mutate

In [36]: [hex(id(m)) for m in methods]
Out[36]: ['0x10581de08', '0x10581d208', '0x105abc988']

但是,它包含了相同的基础函数In [37]: f.mutate is f.mutate Out[37]: False ,它不会发生变化,并且只是类中任何其他函数的一个属性:

Foo.mutate

答案 2 :(得分:2)

这里发生的事情是两件事 1.项目被创建为类变量
2. leaf1作为组件添加:Composite('leaf1')因此拥有类变量items

这两个一起意味着leaf1.print2()将递归地自行调用