Python:错误地使用类变量?
我有以下课程:
class A(object):
x = 1
class B(A):
pass
class C(A):
pass
当我打印x每个类的值时,我得到:
>>>A.x, B.x, C.x
(1,1,1)
然后我分配2给B.x
B.x = 2
A.x, B.x, C.x
>>>(1,2,1)
一切正常,但是当我分配3给A.x我时:
A.x=3
A.x, B.x, C.x
>>>(3,2,3)
我以为它会回来(3,2,1)。
回答
这就是 Python 中继承的基本工作原理:对于类级变量,它首先检查类的命名空间,然后按照方法解析顺序检查每个类的命名空间。所以,无论是B和C继承x来自A:
In [1]: class A(object):
...: x = 1
...: class B(A):
...: pass
...: class C(A):
...: pass
...:
In [2]: vars(A)
Out[2]:
mappingproxy({'__module__': '__main__',
'x': 1,
'__dict__': <attribute '__dict__' of 'A' objects>,
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'__doc__': None})
In [3]: vars(B)
Out[3]: mappingproxy({'__module__': '__main__', '__doc__': None})
In [4]: vars(C)
Out[4]: mappingproxy({'__module__': '__main__', '__doc__': None})
当您请求B.xor 时C.x,它会查看该类的命名空间,没有找到任何"x",然后尝试A的命名空间,找到它并返回它。
现在,当您将变量分配给B.x = 2时,会将其B直接添加到的类命名空间:
In [5]: B.x = 2
...:
In [6]: vars(B)
Out[6]: mappingproxy({'__module__': '__main__', '__doc__': None, 'x': 2})
同样,当您将其分配给 时A.x=3,它会覆盖旧值:
In [7]: A.x=3
...:
In [8]: vars(A)
Out[8]:
mappingproxy({'__module__': '__main__',
'x': 3,
'__dict__': <attribute '__dict__' of 'A' objects>,
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'__doc__': None})
In [9]: vars(B)
Out[9]: mappingproxy({'__module__': '__main__', '__doc__': None, 'x': 2})
In [10]: vars(C)
Out[10]: mappingproxy({'__module__': '__main__', '__doc__': None})
所以现在,和以前一样,当你寻找时C.x,它没有找到它自己的,然后它在x里面A寻找,并找到它。
注意,继承对于实例也是如此,只是它首先检查实例命名空间,然后是实例类的命名空间,然后是方法解析顺序中类的所有命名空间。