Python中的对象/类属性 - 发生了什么?

1 投票
6 回答
1575 浏览
提问于 2025-04-15 23:59

有没有人能解释一下为什么Python会这样做呢?

>>> class Foo(object):
...   bar = []
...
>>> a = Foo()
>>> b = Foo()
>>> a.bar.append(1)
>>> b.bar
[1]
>>> a.bar = 1
>>> a.bar
1
>>> b.bar
[1]
>>> a.bar = []
>>> a.bar
[]
>>> b.bar
[1]
>>> del a.bar
>>> a.bar
[1]

这真让人感到困惑!

6 个回答

0

当你在类里面这样声明一个元素时,这个元素会被这个类的所有实例共享。要想让每个实例都有自己独立的成员,就需要在 __init__ 方法里单独创建,像下面这样:

class Foo(object):
    def __init__(self):
        self.bar = []
7

这是因为你写的方式,bar 是一个类变量,而不是实例变量。

要定义一个实例变量,你需要在构造函数里绑定它:

class Foo(object):
  def __init__(self):
    self.bar = []

注意,现在它属于一个特定的 Foo 实例(self),而不是 Foo 类。这样,当你给它赋值时,你会看到你期待的结果。

0

正如其他人所说,这段代码创建的是一个类变量,而不是实例变量。你需要在 __init__ 方法里进行赋值,才能创建一个实例变量。

希望下面这个带注释的代码能帮助你理解每个步骤发生了什么:

>>> class Foo(object):
...   bar = []          # defines a class variable on Foo (shared by all instances)
...
>>> a = Foo()
>>> b = Foo()
>>> a.bar.append(1)     # appends the value 1 to the previously empty list Foo.bar
>>> b.bar               # returns the value of the class variable Foo.bar
[1]
>>> a.bar = 1           # binds 1 to the instance variable a.bar, masking the access
>>> a.bar               # you previously had to the class variable through a.bar
1
>>> b.bar               # b doesn't have an instance variable 'bar' so this still
[1]                     # returns the class variable
>>> a.bar = []          # bind a's instance variable to to an empty list
>>> a.bar
[]
>>> b.bar               # b doesn't have an instance variable 'bar' so this still
[1]                     # returns the class variable
>>> del a.bar           # unbinds a's instance variable unmasking the class variable
>>> a.bar               # so a.bar now returns the list with 1 in it.
[1]

另外,在每条语句执行后,打印出 Foo.bar 的值(这是通过类访问的类变量,而不是通过实例访问的)可能会帮助你更清楚地理解发生了什么。

撰写回答