在__init__之外初始化字段

时间:2012-09-16 17:34:39

标签: python initialization python-2.7

我需要一些帮助才能理解python初始化是如何工作的。我有一个类(Bar),另一个类(Foo)作为字段/变量。当我尝试直接在Bar(而不是类__init__)中初始化此变量时,Bar的所有实例都将指向相同的Foo。但是如果我有一个__init__方法,就像在Bar2中那样,每个Bar2实例都会有一个唯一的Foo实例。这里发生了什么?

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 "\nBar2"
print first
print second
print first.foo
print second.foo

输出例如是:

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实例。为什么呢?

修改:为 Bar 打印 first.foo 两次更正了错误。结果行为仍然如输出中所示。

4 个答案:

答案 0 :(得分:2)

Bar.foo是一个类变量。它在创建类时初始化一次。

(请注意,您的代码也会打印first.foo两次,所以难怪输出是相同的。)

答案 1 :(得分:2)

Python是一种动态语言。在像Java这样的静态语言中,编译器读取代码,查找类定义,确定它们是否正确并相应地生成一些代码。在python中,类定义(或函数定义)只是一个语句,就像对变量的赋值一样。语法略有不同。

定义类时,解释器运行类定义,即它在类行之后运行所有代码。如果找到函数定义,它也会运行它们,即定义函数并将它们绑定到函数名称。由于类和函数定义是任何其他赋值的语句,因此您也可以在许多地方使用它们。例如如下:

def foo():
  class A: pass
  a = A()
  a.msg = "Hello"
  return a

因为python是鸭子类型(如果它像鸭子一样嘎嘎叫,看起来像一个,它就是一个),函数foo的用户甚至不必知道调用类的内容,他们只需要知道foo返回一个带有成员msg的对象。你可以这样使用它:

a = foo()
print a.msg

因此,在您的示例中,执行Bar的定义时,将运行classes语句,包括创建Foo对象。当执行Bar2的定义时,classes语句在它们之间运行一个名为 init 的函数的定义。 Python使用this作为要调用的函数的名称,在创建对象时(在调用另一个函数__new__之后,除此之外)。

同样,类定义(类中的代码,Bar创建Foo对象的代码)在引入类时只运行一次。每次创建一个新对象时都会一次又一次地调用__init__,因此在Bar2中,一次又一次地创建一个Foo。

据我所知,“foo = None”是多余的,不是真的需要它。在python中,您可以从任何地方添加实例变量,甚至可以从类外部添加实例变量,也可以从__init__内部添加。

答案 2 :(得分:0)

first = Bar()
second = Bar()

print "Bar"
print first
print second
print first.foo
print first.foo

在这里,你打印first.foo两次,这就是打印相同foo对象的原因。

first = Bar2()
second = Bar2()

print "\nBar2"
print first
print second
print first.foo
print second.foo

这里,foo是Bar2类中的一个静态变量,这就是为什么两个对象都指向同一个foo对象,用第二个构造构造。

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的每个对象都是唯一的。

答案 3 :(得分:0)

类也是对象,它们有自己的一组变量。不仅如此,当Python无法在对象中找到变量时,它会在类中查看它是否可以在那里找到它,这就是它所使用的。由于该类在该类的所有对象之间共享,因此该类中的变量也是如此。