3

我需要一些帮助来理解 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

4 回答 4

2

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

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

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

因为 python 是鸭子类型的(如果它像鸭子一样嘎嘎叫,看起来像一只,那就是一只),函数 foo 的用户甚至不必知道类被称为什么,他们只需要知道 foo 返回一个对象与会员味精。你会像这样使用它:

a = foo()
print a.msg

因此,在您的示例中,执行 Bar 的定义时,将运行 classes 语句,包括创建 Foo 对象。当 Bar2 的定义被执行时,类语句在其中运行一个名为init的函数的定义。Python 使用 this 作为要调用的函数的名称,当一个对象被创建时(在调用另一个函数之后__new__,但这不是重点)。

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

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

于 2012-09-16T19:46:52.210 回答
2

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

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

于 2012-09-16T17:36:27.417 回答
1

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

于 2012-09-16T17:39:49.103 回答
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 对象,用 second 的构造来构造。

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

于 2012-09-16T17:39:10.517 回答