这是一个完全理论的问题。假设以下代码:
>>> class C:
... a = 10
... def f(self): self.a = 999
...
>>>
>>> C.a
10
>>> c = C()
>>> c.a
10
>>> c.f()
>>> c.a
999
此时,类变量C.a
是否仍然可以通过对象c
访问?
这是一个完全理论的问题。假设以下代码:
>>> class C:
... a = 10
... def f(self): self.a = 999
...
>>>
>>> C.a
10
>>> c = C()
>>> c.a
10
>>> c.f()
>>> c.a
999
此时,类变量C.a
是否仍然可以通过对象c
访问?
c.__class__.a
或 type(c).a
。两者略有不同,旧式类(希望现在都已经消失了 - 但你永远不知道...)的 type()
是 <type 'instance'>
(而 __class__
的效果如预期),而对于新式类,type()
与 __class__
相同,除非对象覆盖属性访问。所有类变量都可以通过从该类实例化的对象访问。
>>> class C:
... a = 10
... def f(self): self.a = 999
...
>>> C.a
10
>>> c = C()
>>> c.a
10
>>> c.f()
>>> c.a
999
>>> c.__class__.a
10
>>> c.a
999
>>> del(c.a)
>>> c.a
10
属性首先在对象命名空间中搜索,然后在类中搜索。
a
的类属性,也有名为a
的实例属性。下面我来举个例子:>>> class Foo(object):
... a = 10
...
>>> c = Foo()
>>> c.a
10
>>> c.a = 100 # this doesn't have to be done in a method
>>> c.a # a is now an instance attribute
100
>>> Foo.a # that is shadowing the class attribute
10
>>> del c.a # get rid of the instance attribute
>>> c.a # and you can see the class attribute again
10
>>>
区别在于一个存在于 Foo.__dict__
作为一个条目,另一个存在于 c.__dict__
中。当你访问 instance.attribute
时,如果存在,则返回 instance.__dict__['attribute']
,如果不存在,则检查 type(instance).__dict__['attribute']
。然后会检查类的超类,但这变得稍微复杂了一些。
但无论如何,主要问题是不需要是其中之一。类和实例都可以拥有具有相同名称的不同属性,因为它们存储在两个单独的字典中。
是的,您可以通过对象 c 访问 a ,例如 c.a 。该值最初为10。
但是,如果您调用c.f()
,则c.a
的值现在将为999,但是C.a
仍将为10。同样,如果您现在将C.a
更改为1000,则c.a
仍将为999。
基本上,当您实例化C
的实例时,它将使用类变量作为自己的a
值,直到您更改该实例的a
值,此时它将不再与类共享a
。