我是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:类和实例属性之间的区别,但它没有回答我的问题.
谁能解释为什么会有区别?谢谢
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.
>>> 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)
你在第二个例子中没有做同样的事情.在第一个示例中,您将分配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属性.
归档时间: |
|
查看次数: |
3520 次 |
最近记录: |