python:类属性和实例属性

use*_*869 6 python

我是python的新手,并且知道类属性就像C++中的静态数据成员一样.但是,在尝试以下代码后我感到困惑:

>>> class Foo:
...     a=1
... 
>>> f1=Foo();
>>> f2=Foo()
>>> f1.a
1
>>> f1.a=5
>>> f1.a
5
>>> f2.a
1
Run Code Online (Sandbox Code Playgroud)

f2.a也不应该等于5吗?

如果a被定义为列表而不是整数,则行为是预期的:

>>> class Foo:
...     a=[]
... 
>>> f1=Foo();
>>> f2=Foo()
>>> f1.a
[]
>>> f1.a.append(5)
>>> f1.a
[5]
>>> f2.a
[5]
Run Code Online (Sandbox Code Playgroud)

我看了 Python:类和实例属性之间的区别,但它没有回答我的问题.

谁能解释为什么会有区别?谢谢

int*_*ted 9

Python的类属性和对象属性存储在单独的字典中.对于对象f1,可以分别通过f1.__class__.__dict__和访问它们f1.__dict__.执行print f1.__class__ is Foo将输出True.

当您引用对象的属性时,Python首先尝试在对象字典中查找它.如果它没有找到它,它会检查类字典(依此类推依赖继承).

分配给时f1.a,您要为对象字典添加条目f1.随后的查找f1.a将找到该条目.查找f2.a仍然会找到class属性 - 类属性字典中的条目.

您可以通过删除它来使值f1.a恢复为1:

del f1.a
Run Code Online (Sandbox Code Playgroud)

这将删除a对象字典中的条目f1,并且后续查找将继续到类字典.那么,之后,print f1.a将输出1.


Tim*_*ker 7

>>> class Foo:
...     a=1
... 
>>> f1=Foo()
>>> f2=Foo()
>>> f1.a    # no instance attribute here in f1, so look up class attribute in Foo
1
>>> f1.a=5  # create new instance attribute in f1
>>> f1.a    # instance attribute here. Great, let's use this.
5
>>> f2.a    # no instance attribute in f2, look up class attribute in Foo
1
>>>
>>> class Foo:
...     a=[]
... 
>>> f1=Foo()
>>> f2=Foo()
>>> f1.a            # no instance attribute - look up class attribute in Foo
[]
>>> f1.a.append(5)  # no instance attribute, modify class attribute in-place
>>> f1.a            # no instance attribute - look up class attribute in Foo
[5]
>>> f2.a            # same here
[5]
Run Code Online (Sandbox Code Playgroud)


lar*_*sks 7

你在第二个例子中没有做同样的事情.在第一个示例中,您将分配f1.a一个新值:

f1.a = 5
Run Code Online (Sandbox Code Playgroud)

在第二个示例中,您只是扩展一个列表:

f1.a.append(5)
Run Code Online (Sandbox Code Playgroud)

这并没有改变f1.a指向的东西.如果你是这样做的话:

f1.a = [5]
Run Code Online (Sandbox Code Playgroud)

您会发现这与第一个示例的行为相同.

但请考虑这个例子:

>>> f1=Foo()
>>> f2=Foo()
>>> Foo.a = 5
>>> f1.a
5
>>> f2.a
5
Run Code Online (Sandbox Code Playgroud)

在此示例中,我们实际上是在更改属性的值,并且更改在类的所有实例中都可见.键入时:

f1.a = 5
Run Code Online (Sandbox Code Playgroud)

您正在使用实例属性覆盖class属性.

  • "你用实例属性覆盖了class属性." 我不这么认为.class属性保持不变.在用户11869的代码中,属性**a**在**f1**的namspace中由指令``f1.a = 5``创建,因为此属性之前不存在,因为它是使用**\_\_ _ dict __**在我的回答中显示 (2认同)