Initializing field outside __init__
我需要一些帮助来理解Python初始化是如何工作的。我有一个类(bar),另一个类(foo)作为字段/变量。当我试图在bar中直接初始化这个变量时(而不是在类uu init_uuu中),bar的所有实例都将指向相同的foo。但是如果我有一个uuu init_uuu方法,就像在bar2中一样,每个bar2实例都有一个唯一的foo实例。这里发生了什么?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | class Foo(): number = 0 class Bar(): foo = Foo() class Bar2(): foo = None def __init__(self): self.foo = Foo() first = Bar() second = Bar() print"Bar" print first print second print first.foo print second.foo first = Bar2() second = Bar2() print" Bar2" print first print second print first.foo print second.foo |
例如,输出为:
1 2 3 4 5 6 7 8 9 10 11 | Bar <\__main__.Bar instance at 0x025B2AF8> <\__main__.Bar instance at 0x025B2B20> <\__main__.Foo instance at 0x004A3AA8> <\__main__.Foo instance at 0x004A3AA8> Bar2 <\__main__.Bar2 instance at 0x025B2B48> <\__main__.Bar2 instance at 0x025B2AF8> <\__main__.Foo instance at 0x025B2B70> <\__main__.Foo instance at 0x025B2B98> |
号
使用BAR,两个实例将引用同一个foo实例。为什么?
编辑:修正错误,在第一个.foo中打印两次。结果行为仍然如输出中所示。
python是一种动态语言。在像Java这样的静态语言中,编译器读取代码,查找类定义,计算出它们是否正确,并相应地生成一些代码。在Python中,类定义(或函数定义)和其他任何定义一样,只是一个语句,就像对变量的赋值一样。语法有点不同。
定义类时,解释器运行类定义,即在类行之后运行所有代码。如果找到函数定义,它也会运行它们,即定义函数并将它们绑定到函数名。由于类和函数定义与任何其他赋值一样都是语句,因此您也可以在许多地方使用它们。例如如下:
1 2 3 4 5 | def foo(): class A: pass a = A() a.msg ="Hello" return a |
。
因为python是duck类型的(如果它像duck一样嘎嘎叫,看起来像duck,那么它就是duck类型的),函数foo的用户甚至不需要知道该类的名称,他们只需要知道foo返回一个带有member msg的对象。您可以这样使用它:
1 2 | a = foo() print a.msg |
所以在您的示例中,当执行bar的定义时,将运行classes语句,包括创建foo对象。当执行bar2的定义时,classes语句在其中运行一个名为init的函数的定义。当一个对象被创建时(在调用另一个函数
因此,类定义(类内的代码,其中bar创建foo对象)在引入类时只运行一次。每次制造一个新对象时,都会一次又一次地调用
据我所知,"foo=none"是多余的,实际上并不需要。在python中,您可以从任何地方添加实例变量,甚至可以从类外部,当然也可以从
(请注意,您的代码ALS打印了两次
类也是对象,它们有自己的变量集。不仅如此,当Python在对象中找不到变量时,它会在类中查找是否可以在那里找到它,这就是它所使用的。因为类是在该类的所有对象之间共享的,所以该类中的变量也是共享的。
1 2 3 4 5 6 7 8 | first = Bar() second = Bar() print"Bar" print first print second print first.foo print first.foo |
这里,您要打印两次first.foo,这就是为什么打印相同的foo对象。
1 2 3 4 5 6 7 8 9 | first = Bar2() second = Bar2() print" Bar2" print first print second print first.foo print second.foo |
号
这里,foo是类bar2中的一个静态变量,这就是为什么两个对象都指向同一个foo对象,用second构造。
1 2 3 4 5 6 7 8 9 | class Bar2(): foo = None def __init__(self): self.foo = Foo() class Bar(): def __init__(self): self.foo = Foo() |
在bar2中,bar2的所有对象都将使foo对象指向在bar2的最后一个构造对象构造时构造的相同对象。
在BAR中,所有FOO对象对于BAR的每个对象都是唯一的,除非另有说明。