对象 vs 类变量

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
你尝试了它,它起作用了。这不是理论上的。这甚至不是一个真正的问题。它有效了。你还想知道什么? - S.Lott
我想知道什么?“此时,类变量C.a是否仍然可以通过对象c访问?” - Boris Gorelik
4个回答

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
在您为类实例分配变量后,既有名为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']。然后会检查类的超类,但这变得稍微复杂了一些。

但无论如何,主要问题是不需要是其中之一。类和实例都可以拥有具有相同名称的不同属性,因为它们存储在两个单独的字典中。


这是最清晰的解释。感谢您提供了一个好答案。 - Paul McMillan

1

是的,您可以通过对象 c 访问 a ,例如 c.a 。该值最初为10。

但是,如果您调用c.f(),则c.a的值现在将为999,但是C.a仍将为10。同样,如果您现在将C.a更改为1000,则c.a仍将为999。

基本上,当您实例化C的实例时,它将使用类变量作为自己的a值,直到您更改该实例的a值,此时它将不再与类共享a


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接