2010-10-12 58 views
3

这是一个完全理论上的问题。假设下面的代码:对象与类变量

>>> 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仍然可以访问?

+1

你试过了,它工作。这不是理论上的。这甚至不是一个真正的问题。有效。你还想知道什么? – 2010-10-12 21:32:49

+0

我想知道什么? “在这一点上,类变量C.a仍然可以通过对象c访问吗?” – 2010-10-13 04:40:31

回答

4

是的,虽然c.__class__.atype(c).a。这两者在旧式课程中稍有不同(希望那些现在都已经死了 - 但你永远不知道......)有type()<type 'instance'>(和__class__按预期工作),而对于新式课程,type()是相同的到__class__除非对象覆盖属性访问权限。

1

所有类变量都可以通过从该类实例化的对象访问。

>>> 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 

属性首先在对象命名空间中搜索,然后在类中搜索。

1

是的,您可以从对象c,àla c.a访问a。该值最初将10

但是,如果调用c.f()c.a值现在是999,C.a仍将10.同样的,如果你现在更改C.a,比方说,1000,c.a仍然是999

基本上,当实例的C一个实例,它将使用类变量作为自己的a值,直到您更改该实例的a的价值,在这种情况下,将不再“分享”a同班同学。

1

在类实例上分配给它之后,同时存在名为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']。然后检查该类的超类,但稍微复杂一些。

但无论如何,主要的一点是它不一定是一个或另一个。一个类和一个实例可以具有不同的具有相同名称的属性,因为它们存储在两个单独的字典中。

+0

这是这里最清楚的解释。谢谢你的回答。 – 2010-10-12 21:36:18