最近對Python 的物件引用機制稍微研究了一下,留下筆記,以便查閱。
首先有一點是明確的:「Python 中一切皆物件」。
那麼,這到底代表什麼呢?
如下碼:
#!/usr/bin/env python a = [0, 1, 2] # 来个简单的list # 最初,list 和其中各个元素的id 是这样的。 print 'origin' print id(a),a for x in a: print id(x), x print '----------------------' # 我们把第一个元素改改 print 'after change a[0]' a[0] = 4 print id(a),a for x in a: print id(x), x print '----------------------' # 我们再把第二个元素改改 print 'after change a[1]' a[1] = 5 print id(a),a for x in a: print id(x), x print '----------------------' # 回头看看直接写个0 ,id是多少 print 'how about const 0?' print id(0), 0
運作結果如下:
PastgiftMacbookPro:python pastgift$ ./refTPastgiftMacbookPro:python pastgift$ 1, 2]
4298181328 0
4298181304 1
4298181280 2
----------------------
after change a[0]
4299760200 [4, 1, 2]
4298181304 1
4298181280 2
----------------------
after change a[1]
429976020025,
4298181232 44298181208 54298181280 2----------------------how about 2----------------------how about 2238 從「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 中類別屬性,有人提到「類別屬性在同一類別及其子類別之間共享,修改類別屬性會影響到同一類別及其子類別的所有物件」。 聽著挺嚇人,但仔細研究之後,其實倒也不是什麼大不了的事。 如下程式碼:#!/usr/bin/env python class Bird(object): name = 'bird' talent = ['fly'] class Chicken(Bird): pass bird = Bird(); bird2 = Bird(); # 同类实例 chicken = Chicken(); # 子类实例 # 最开始是这样的 print 'Original attr' print id(bird.name), bird.name print id(bird.talent), bird.talent print id(bird2.name), bird2.name print id(bird2.talent), bird2.talent print id(chicken.name), chicken.name print id(chicken.talent), chicken.talent print '----------------------------' # 换个名字看看 bird.name = 'bird name changed!' print 'after changing name' print id(bird.name), bird.name print id(bird.talent), bird.talent print id(bird2.name), bird2.name print id(bird2.talent), bird2.talent print id(chicken.name), chicken.name print id(chicken.talent), chicken.talent print '----------------------------' # 洗个天赋试试(修改类属性中的元素) bird.talent[0] = 'walk' print 'after changing talent(a list)' print id(bird.name), bird.name print id(bird.talent), bird.talent print id(bird2.name), bird2.name print id(bird2.talent), bird2.talent print id(chicken.name), chicken.name print id(chicken.talent), chicken.talent print '----------------------------' # 换个新天赋树(整个类属性全换掉) bird.talent = ['swim'] print 'after reassign talent' print id(bird.name), bird.name print id(bird.talent), bird.talent print id(bird2.name), bird2.name print id(bird2.talent), bird2.talent print id(chicken.name), chicken.name print id(chicken.talent), chicken.talent print '----------------------------' # 洗掉新天赋树(对新来的类属性中的元素进行修改) bird.talent[0] = 'dance' print 'changing element after reassigning talent' print id(bird.name), bird.name print id(bird.talent), bird.talent print id(bird2.name), bird2.name print id(bird2.talent), bird2.talent print id(chicken.name), chicken.name print id(chicken.talent), chicken.talent print '----------------------------'運作結果: Original attr
4301998000 bird
4301857352 ['fly']
4301998000 bird
4301857352 ['fly']
4301998000 bird
430185735225735252] ----
after changing name
4301986984 bird name changed!
4301857352 ['fly']
43019980075
4301998000 bird
4301857352 ['fly']
----------------------------
after changing talent(a list)
4301986984 bird name changed!
4301857352 ['walk ']
4301998000 bird
4301857352 ['walk']
4301998000 bird
430185735225252-- ------
after reassign talent
4301986984 bird name changed!
4301859512 ['swim']
4301859512 ['swim']
4301998055
4301998000 bird
4301857352 ['walk']
----------------------------
changing element after reassigning talent
4301986984 bird name changed!
4301859512 name changed!
4301859512 [d ']
4301998000 bird
4301857352 ['walk']
4301998000 bird
430185735225252-- ------
在「Origin」的時候,同類對象,子類別對象的相同類別屬性的位址都是相同的-這就是所謂的「共享」。
修改name 之後,只有被修改的物件name 屬性會改變。這是因為對name的賦值運算其實就是換了一個字串,重新引用。字串本身並沒有改變。所以並沒有在同類和子類之間產生互相影響。
接下來,修改talent 中的元素。這時,情況有所改變:同類及其子類別的talent 屬性都一起跟著變了——這很好理解,因為它們都引用的記憶體位址都一樣,引用的是同一個物件。
再接下來,給talent 重新賦值,也就是改成引用另外一個物件。結果是只有本實例的talent 屬性變化了。從記憶體位址可以看出,本實例和其他實例的talent 屬性已經不再指向相同的物件了。就是說「至此,本實例已經是圈外人士了」。
那麼,最後再次修改talent 中元素後,對其他實例無影響的結果也是很好理解了。因為已經是「圈外人士」了嘛,我再怎麼折騰也都是自己的事情了。
所以,「类属性在同类及其子类之间互相影响」必须有一个前提条件:实例建立后,其类属性从来没有被重新赋值过,即类属性依然指向最初所指向的内存地址。
最后提一下对象属性
如下代码:
#!/usr/bin/env python class Bird(object): def __init__(self): self.talent = ['fly'] bird = Bird() bird2 = Bird() # 刚开始的情形 print 'Origin' print id(bird.talent), bird.talent print id(bird2.talent), bird2.talent print '--------------------' # 修改其中一个对象的属性 bird.talent[0] = 'walk' print 'after changing attribute' print id(bird.talent), bird.talent print id(bird2.talent), bird2.talent print '--------------------' # 作死:两个对象的属性指向同一个内存地址,再修改 bird.talent = bird2.talent bird.talent[0] = 'swim' print 'assign to another attribute and change it' print id(bird.talent), bird.talent print id(bird2.talent), bird2.talent print '--------------------'
运行结果:
PastgiftMacbookPro:python pastgift$ ./changeAttributeTest2.py
Origin
4299867632 ['fly']
4299760200 ['fly']
--------------------
after changing attribute
4299867632 ['walk']
4299760200 ['fly']
--------------------
assign to another attribute and change it
4299760200 ['swim']
4299760200 ['swim']
--------------------
由于对象属性就算内容完全一样(刚初始化后的属性内容一般都是一样的),也会分配到完全不同的内存地址上去。所以不存在「同类对象之间影响」的情况。
但如果让一个对象的属性和另一个对象的属性指向同一个地址,两者之间(但也仅限两者之间)便又互相牵连起来。

使用NumPy創建多維數組可以通過以下步驟實現:1)使用numpy.array()函數創建數組,例如np.array([[1,2,3],[4,5,6]])創建2D數組;2)使用np.zeros(),np.ones(),np.random.random()等函數創建特定值填充的數組;3)理解數組的shape和size屬性,確保子數組長度一致,避免錯誤;4)使用np.reshape()函數改變數組形狀;5)注意內存使用,確保代碼清晰高效。

播放innumpyisamethodtoperformoperationsonArraySofDifferentsHapesbyAutapityallate AligningThem.itSimplifififiesCode,增強可讀性,和Boostsperformance.Shere'shore'showitworks:1)較小的ArraySaraySaraysAraySaraySaraySaraySarePaddedDedWiteWithOnestOmatchDimentions.2)

forpythondataTastorage,choselistsforflexibilityWithMixedDatatypes,array.ArrayFormeMory-effficityHomogeneousnumericalData,andnumpyArraysForAdvancedNumericalComputing.listsareversareversareversareversArversatilebutlessEbutlesseftlesseftlesseftlessforefforefforefforefforefforefforefforefforefforlargenumerdataSets; arrayoffray.array.array.array.array.array.ersersamiddreddregro

Pythonlistsarebetterthanarraysformanagingdiversedatatypes.1)Listscanholdelementsofdifferenttypes,2)theyaredynamic,allowingeasyadditionsandremovals,3)theyofferintuitiveoperationslikeslicing,but4)theyarelessmemory-efficientandslowerforlargedatasets.

toAccesselementsInapyThonArray,useIndIndexing:my_array [2] accessEsthethEthErlement,returning.3.pythonosezero opitedEndexing.1)usepositiveandnegativeIndexing:my_list [0] fortefirstElment,fortefirstelement,my_list,my_list [-1] fornelast.2] forselast.2)

文章討論了由於語法歧義而導致的Python中元組理解的不可能。建議使用tuple()與發電機表達式使用tuple()有效地創建元組。 (159個字符)

本文解釋了Python中的模塊和包裝,它們的差異和用法。模塊是單個文件,而軟件包是帶有__init__.py文件的目錄,在層次上組織相關模塊。

文章討論了Python中的Docstrings,其用法和收益。主要問題:Docstrings對於代碼文檔和可訪問性的重要性。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SublimeText3漢化版
中文版,非常好用

WebStorm Mac版
好用的JavaScript開發工具

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)