Python類(lèi)和實(shí)例的屬性機(jī)制原理詳解
實(shí)例是具象化的類(lèi),它可以作為類(lèi)訪問(wèn)所有靜態(tài)綁定到類(lèi)上的屬性,包括類(lèi)變量與方法,也可以作為實(shí)例訪問(wèn)動(dòng)態(tài)綁定到實(shí)例上的屬性。
實(shí)例1:
class A: work = list('hello') kind = list('world') another = 1 def test1(self): print(self.work, self.kind, self.another) self.work[0], self.kind [0] = 't', 't' self.another += 1 print(A.work, A.kind, A.another)if __name__ == '__main__': a = A() a.test1()
輸出結(jié)果:
[’h’, ’e’, ’l’, ’l’, ’o’] [’w’, ’o’, ’r’, ’l’, ’d’] 1[’t’, ’e’, ’l’, ’l’, ’o’] [’t’, ’o’, ’r’, ’l’, ’d’] 1
test1中演示了實(shí)例對(duì)類(lèi)變量的訪問(wèn)與修改,從輸出結(jié)果可以看到,類(lèi)變量work和kind的列表被修改了,而another的值沒(méi)有發(fā)生變化,說(shuō)明如果類(lèi)變量是可變的,那么可以通過(guò)實(shí)例來(lái)對(duì)類(lèi)變量進(jìn)行修改,如果類(lèi)變量不可變,那么實(shí)例無(wú)法修改類(lèi)變量。
實(shí)例2:
class A: work = list('hello') kind = list('world') another = 1 def test2(self): A.work, A.kind = 'hello', ' world' A.another += 2 print(self.__dict__) print(self.work, self.kind, self.another) A.test2 = 13 print(self.test2)if __name__ == '__main__': a = A() a.test2()
輸出結(jié)果:
{’another’: 2} hello world 2 13
test2說(shuō)明了實(shí)例訪問(wèn)類(lèi)變量與方法的機(jī)制,在test1中,已經(jīng)給實(shí)例動(dòng)態(tài)綁定了一個(gè)another的屬性,值為2(因?yàn)橛匈x值語(yǔ)句)。在self.__dict__中可以看到確實(shí)出現(xiàn)了實(shí)例屬性another。
在使用實(shí)例訪問(wèn)屬性(變量與方法)時(shí),如果在實(shí)例的屬性集里沒(méi)有找到對(duì)應(yīng)的屬性,那么就會(huì)到類(lèi)的屬性集里找對(duì)應(yīng)的屬性。self.work和self.kind和類(lèi)變量保持一致,說(shuō)明并沒(méi)有事先在實(shí)例與類(lèi)變量之間建立引用,而是動(dòng)態(tài)查找的。
class A: work = list('hello') kind = list('world') another = 1 def test3(self): print(self.__dict__) self.w, self.k = 0, 1 print(self.__dict__) self.work, self.kind = 4, 4 print(self.__dict__) self.test1 = 12 print(self.__dict__) try: self.test1() except: print('test1 is not a bound method')if __name__ == '__main__': a = A() a.test3()
輸出結(jié)果:
{’another’: 2} {’another’: 2, ’w’: 0, ’k’: 1} {’another’: 2, ’w’: 0, ’k’: 1, ’work’: 4, ’kind’: 4} {’another’: 2, ’w’: 0, ’k’: 1, ’work’: 4, ’kind’: 4, ’test1’: 12} test1 is not a bound method
self.__dict__中保存了動(dòng)態(tài)綁定到實(shí)例的變量與方法,只要出現(xiàn)了賦值語(yǔ)句,都是動(dòng)態(tài)綁定屬性。如果動(dòng)態(tài)綁定的屬性與類(lèi)的變量或方法同名,在查找過(guò)程中就會(huì)覆蓋類(lèi)的變量和方法。
總結(jié)
1. 動(dòng)態(tài)綁定到實(shí)例的屬性位于self.__dict__中
2. 出現(xiàn)self.attribute = XXX之類(lèi)的賦值語(yǔ)句都是在往實(shí)例上動(dòng)態(tài)綁定屬性
3. 實(shí)例查找屬性的流程:self.work -> self.__dict__['work'] or cls.work,這是一個(gè)動(dòng)態(tài)的過(guò)程,實(shí)例中的同名屬性會(huì)覆蓋類(lèi)變量或方法,類(lèi)變量或方法的修改會(huì)實(shí)時(shí)影響實(shí)例查找屬性的結(jié)果
4. 如果類(lèi)變量是可修改的,如列表,字典等,可以通過(guò)實(shí)例來(lái)修改類(lèi)變量,方法是不可修改的,故無(wú)法通過(guò)實(shí)例修改方法
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. 簡(jiǎn)述JAVA同步、異步、阻塞和非阻塞之間的區(qū)別2. Python TestSuite生成測(cè)試報(bào)告過(guò)程解析3. 詳解JAVA 強(qiáng)引用4. IntelliJ IDEA設(shè)置默認(rèn)瀏覽器的方法5. 在JSP中使用formatNumber控制要顯示的小數(shù)位數(shù)方法6. 使用Python3 poplib模塊刪除服務(wù)器多天前的郵件實(shí)現(xiàn)代碼7. IntelliJ IDEA設(shè)置背景圖片的方法步驟8. 解決AJAX返回狀態(tài)200沒(méi)有調(diào)用success的問(wèn)題9. 深入了解JAVA 軟引用10. SpringBoot集成mqtt的多模塊項(xiàng)目配置詳解
