我有以下类:
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
都从A
:继承了x
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.x
或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
时,它没有找到它自己的,然后它在A
中寻找x
,并找到它。
注意,继承对实例也是这样工作的,只是它首先检查实例命名空间,然后检查实例类的命名空间,然后按方法解析顺序检查类的所有命名空间。
我认为是因为这个事实,您没有设置"a";字段,例如";C";班
因此,它从超类("父类"(获得其默认值。
如果设置"0"的值;a";在c实例中,您将得到"(3,2,1(";。