python 命名空間字典
模塊的命名空間實際上是以字典的形式實現的,並且可以由內置屬性__dict__顯示這一點,類和實例對象也是如此:屬性點號運算其實內部就是字典的索引運算,而屬性繼承其實就是搜索聯結的字典而已,實例和類對象都是Python帶有鏈接的字典
#space.py
>>> class super:
def hello(self):
self.data1='spam'
>>> class sub(super):
def hola(self):
self.data2='egg'
>>> X=sub()
>>> X.__dict__
{}
>>> X.__class__
<class __main__.sub at 0x01F85DF8>
>>> sub.__bases__
(<class __main__.super at 0x01F85D88>,)
>>> super.__bases__
()
>>> 解釋:
製作子類的實例時,該實例一開始回事空的命名空間字典,但是有鏈接會指向它的類,讓繼承搜索能順着尋找,實際上,繼承樹可在特殊的屬性中看到,實例中有個__class__屬性連接到了它的類,而類有個__bases__屬性,是一個元組,其中包含了通往更高的超類的鏈接
#space.py continue
>>> Y=sub()
>>> X.hello()
>>> X.__dict__
{'data1': 'spam'}
>>> X.hola()
>>> X.__dict__
{'data1': 'spam', 'data2': 'egg'}
>>> sub.__dict__
{'__module__': '__main__', '__doc__': None, 'hola': <function hola at 0x01F8CF70>}
>>> super.__dict__
{'__module__': '__main__', 'hello': <function hello at 0x01F8CF30>, '__doc__': None}
>>> sub.__dict__.keys(),super.__dict__.keys()
(['__module__', '__doc__', 'hola'], ['__module__', 'hello', '__doc__'])
>>> Y.__dict__
>>>
{}
>>>>>>解釋
當類爲self屬性賦值時,會填入實例對象,也就說屬性最後會位於實例的屬性命名空間字典內,而不是類的。實例對象的命名空間保存了數據,會隨實例的不同而不同,而self正式進入其命名空間的鉤子
類字典內的其他含有下劃線變量名。Python會自動設置這些變量
每個實例都有獨立的命名空間字典
因爲屬性實際是Python的字典鍵,那麼有兩種方式可以讀取並對其進行賦值,通過點號運算或者通過鍵索引運算
>>> X.data1,X.__dict__['data1']
('spam', 'spam')
>>> X.data3='totast'
>>> X.__dict__
{'data1': 'spam', 'data3': 'totast', 'data2': 'egg'}
>>> X.__dict__['data4']='fasdfsa'
>>> X.__dict__
{'data4': 'fasdfsa', 'data1': 'spam', 'data3': 'totast', 'data2': 'egg'}
例子:打印繼承體系中類名
#classtree.py
def selftest():
class A:pass
class B(A):pass
class C(A):pass
class D(B,C):pass
class E:pass
class F(D,E):pass
instancetree(B())
instancetree(F())
if __name__=='__main__':
selftest()
程序運行結果:
Tree of <__main__.B instance at 0x01EB29B8>
... B
...... A
Tree of <__main__.F instance at 0x01EB29B8>
... F
...... D
......... B
............ A
......... C
............ A
...... E