python中的引用类型_Python 中的引用和类属性的初步理解
最近對Python 的對象引用機制稍微研究了一下,留下筆記,以供查閱。
首先有一點是明確的:「Python 中一切皆對象」。
那么,這到底意味著什么呢?
如下代碼:
#!/usr/bin/env python
a= [0, 1, 2] #來個簡單的list
#最初,list 和其中各個元素的id 是這樣的。
print 'origin'
printid(a),afor x ina:printid(x), xprint '----------------------'
#我們把第一個元素改改
print 'after change a[0]'a[0]= 4
printid(a),afor x ina:printid(x), xprint '----------------------'
#我們再把第二個元素改改
print 'after change a[1]'a[1] = 5
printid(a),afor x ina:printid(x), xprint '----------------------'
#回頭看看直接寫個0 ,id是多少
print 'how about const 0?'
print id(0), 0
運行結果如下:
PastgiftMacbookPro:python pastgift$ ./refTest.py
Origin4299760200 [0, 1, 2]429818132804298181304 1
4298181280 2
----------------------after change a[0]4299760200 [4, 1, 2]4298181232 4
4298181304 1
4298181280 2
----------------------after change a[1]4299760200 [4, 5, 2]4298181232 4
4298181208 5
4298181280 2
----------------------how about const 0?4298181328 0
從「Origin」部分來看,list 中各個元素的地址之間都正好相差24,依次指向各自的數據——這讓我想到了數組。
當修改a[0] 的值之后,發現,a[0] 的地址發生了變化。也就是說,賦值語句實際上只是讓a[0] 重新指向另一個對象而已。此外,還注意到,a[0] 的地址和a[2]的地址相差48(2個24)。
當再次修改a[1] 之后,同樣地,a[1] 的地址也發生變化,有趣的是,這次a[1] 的地址和a[0] 的地址又相差24,和原先的a[2] 相差72(3個24)。
最后,當直接把數字0的地址打印出來后,發現它的地址和最開始的a[0] 的地址完全一樣。
至此,基本可以說明,就算是list 中的元素,其實也是引用。修改list 中的元素,實際上還是在修改引用而已。
對于Python 中類屬性,有人提到過「類屬性在同一類及其子類之間共享,修改類屬性會影響到同一類及其子類的所有對象」。
這里提到的:http://www.cnblogs.com/vamei/archive/2012/06/02/2532018.html
聽著挺嚇人,但仔細研究之后,其實倒也不是什么大不了的事情。
如下代碼:
#!/usr/bin/env python
classBird(object):
name= 'bird'talent= ['fly']classChicken(Bird):passbird=Bird();
bird2= Bird(); #同類實例
chicken = Chicken(); #子類實例
#最開始是這樣的
print 'Original attr'
printid(bird.name), bird.nameprintid(bird.talent), bird.talentprintid(bird2.name), bird2.nameprintid(bird2.talent), bird2.talentprintid(chicken.name), chicken.nameprintid(chicken.talent), chicken.talentprint '----------------------------'
#換個名字看看
bird.name = 'bird name changed!'
print 'after changing name'
printid(bird.name), bird.nameprintid(bird.talent), bird.talentprintid(bird2.name), bird2.nameprintid(bird2.talent), bird2.talentprintid(chicken.name), chicken.nameprintid(chicken.talent), chicken.talentprint '----------------------------'
#洗個天賦試試(修改類屬性中的元素)
bird.talent[0] = 'walk'
print 'after changing talent(a list)'
printid(bird.name), bird.nameprintid(bird.talent), bird.talentprintid(bird2.name), bird2.nameprintid(bird2.talent), bird2.talentprintid(chicken.name), chicken.nameprintid(chicken.talent), chicken.talentprint '----------------------------'
#換個新天賦樹(整個類屬性全換掉)
bird.talent = ['swim']print 'after reassign talent'
printid(bird.name), bird.nameprintid(bird.talent), bird.talentprintid(bird2.name), bird2.nameprintid(bird2.talent), bird2.talentprintid(chicken.name), chicken.nameprintid(chicken.talent), chicken.talentprint '----------------------------'
#洗掉新天賦樹(對新來的類屬性中的元素進行修改)
bird.talent[0] = 'dance'
print 'changing element after reassigning talent'
printid(bird.name), bird.nameprintid(bird.talent), bird.talentprintid(bird2.name), bird2.nameprintid(bird2.talent), bird2.talentprintid(chicken.name), chicken.nameprintid(chicken.talent), chicken.talentprint '----------------------------'
運行結果:
PastgiftMacbookPro:python pastgift$ ./changeAttributeTest.py
Original attr4301998000bird4301857352 ['fly']4301998000bird4301857352 ['fly']4301998000bird4301857352 ['fly']----------------------------after changing name4301986984bird name changed!4301857352 ['fly']4301998000bird4301857352 ['fly']4301998000bird4301857352 ['fly']----------------------------after changing talent(a list)4301986984bird name changed!4301857352 ['walk']4301998000bird4301857352 ['walk']4301998000bird4301857352 ['walk']----------------------------after reassign talent4301986984bird name changed!4301859512 ['swim']4301998000bird4301857352 ['walk']4301998000bird4301857352 ['walk']----------------------------changing element after reassigning talent4301986984bird name changed!4301859512 ['dance']4301998000bird4301857352 ['walk']4301998000bird4301857352 ['walk']----------------------------
在「Origin」的時候,同類對象,子類對象的相同類屬性的地址都是相同的——這就是所謂的「共享」。
修改name 之后,只有被修改的對象name 屬性發生變化。這是因為對name的賦值操作實際上就是換了一個字符串,重新引用。字符串本身并沒有發生變化。所以并沒有在同類和子類之間產生互相影響。
接下來,修改talent 中的元素。這時,情況有所改變:同類及其子類的talent 屬性都一起跟著變了——這很好理解,因為它們都引用的內存地址都一樣,引用的是同一個對象。
再接下來,給talent 重新賦值,也就是改成引用另外一個對象。結果是只有本實例的talent 屬性變化了。從內存地址可以看出,本實例和其他實例的talent 屬性已經不再指向相同的對象了。就是說「至此,本實例已經是圈外人士了」。
那么,最后再次修改talent 中元素后,對其他實例無影響的結果也是很好理解了。因為已經是「圈外人士」了嘛,我再怎么折騰也都是自己的事情了。
所以,「類屬性在同類及其子類之間互相影響」必須有一個前提條件:實例建立后,其類屬性從來沒有被重新賦值過,即類屬性依然指向最初所指向的內存地址。
最后提一下對象屬性
如下代碼:
#!/usr/bin/env python
classBird(object):def __init__(self):
self.talent= ['fly']
bird=Bird()
bird2=Bird()#剛開始的情形
print 'Origin'
printid(bird.talent), bird.talentprintid(bird2.talent), bird2.talentprint '--------------------'
#修改其中一個對象的屬性
bird.talent[0] = 'walk'
print 'after changing attribute'
printid(bird.talent), bird.talentprintid(bird2.talent), bird2.talentprint '--------------------'
#作死:兩個對象的屬性指向同一個內存地址,再修改
bird.talent =bird2.talent
bird.talent[0]= 'swim'
print 'assign to another attribute and change it'
printid(bird.talent), bird.talentprintid(bird2.talent), bird2.talentprint '--------------------'
運行結果:
PastgiftMacbookPro:python pastgift$ ./changeAttributeTest2.py
Origin4299867632 ['fly']4299760200 ['fly']--------------------after changing attribute4299867632 ['walk']4299760200 ['fly']--------------------assign to another attributeandchange it4299760200 ['swim']4299760200 ['swim']--------------------
由于對象屬性就算內容完全一樣(剛初始化后的屬性內容一般都是一樣的),也會分配到完全不同的內存地址上去。所以不存在「同類對象之間影響」的情況。
但如果讓一個對象的屬性和另一個對象的屬性指向同一個地址,兩者之間(但也僅限兩者之間)便又互相牽連起來。
總結
以上是生活随笔為你收集整理的python中的引用类型_Python 中的引用和类属性的初步理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python数据的格式输出_python
- 下一篇: python把数据写入excel_Pyt