標籤:aac rar mep 基礎 ini tis igp 對象 rod
轉自:http://www.cnblogs.com/Eva-J/p/5044411.html
什麼是靜態欄位
在開始之前,先,解釋一下什麼是類的靜態欄位(我有的時候會叫它類的靜態變數,總之說的都是它。後面大多數情況可能會簡稱為類變數。):
我們看上面的例子,這裡的money就是靜態欄位,首先看它的位置,是在father類中,而不是在__init__中。那麼一個小小的靜態欄位,我為什麼要特意寫一篇番外給它呢?耐著性子看下去,你就會發現一個小小的類變數,卻折射出了整個類的世界。
首先我們先來解釋一下什麼叫做靜態欄位:
我們看上面的例子,左中右三張圖,左邊是純淨的代碼,中間是我給代碼加上的記憶體載入過程,右邊是執行結果。我們在這裡先看中間的圖,來看這個檔案載入的過程。
1.將類存入了記憶體 2.將money變數放入了記憶體 3.將__init__方法的地址放入了記憶體
接下來我們執行了一個__dict__方法,我們看右邊圖中現實的執行結果,發現這個時候記憶體中已經存入了money這個變數,它隨著這個程式 的執行產生,隨著程式的結束而消失,這樣和程式‘共存亡’的欄位,我們就叫它靜態欄位。它就像是一個全域變數,不屬於任何一個對象,我們可以直接使用類來 調用,也可以在對象使用方法的時候使用它。它是對象共用的變數,存在類的記憶體裡。
靜態欄位的調用方法
剛剛我們知道了什麼是靜態欄位,現在我們就來看看靜態欄位是怎麼使用的?
上面給出了兩種使用方式,類調用和對象調用,哎?看起來好像可以哎!我們再來修改一下類變數瞧瞧:
我們看,當我們使用 類名.靜態欄位名 修改類變數之後,使用類或者對象去調用這個靜態欄位,發現它們都產生了變化。好像一切都在我們的預料之中哎,這樣的話對象和類都可以使用類變數的樣子!如果你們真的信了那就太天真了。。。看看下面這個例子:
看上面的圖,我是接著上面的例子寫的,黃框框裡是我加上的內容,我們結果中最後列印出來的內容,哎?我們看到了什嗎?好像對象調用的類變數只是 針對各自的對象發生了改變,並沒有改變類中money變數的值,說好的全域變數呢?這個現象是怎麼發生的呢?我們不防來推理一下:
看上面兩張圖,左邊是正常的邏輯,當我們類的記憶體中有一個靜態欄位的時候,我們使用類去調用這個欄位,自然找到的是靜態欄位,當我們使用對象去 調用的時候,這個對象指標先在自己的記憶體裡找了找,發現沒找到,於是就用對象中維護的類指標到類的記憶體中去找,果然找到了money,於是歡歡喜喜的列印 了出來,我們也如願以償的看到了想要的結果。當我們使用 類 去調用這個靜態欄位進行修改的時候,我們修改的是 類 的記憶體中維護的money欄位,所以並沒有影響上述過程。
再看右邊這張圖,當我們使用對象去調用並改變一個類的靜態欄位的時候,它們在自己的記憶體中並沒有money欄位,所以還是通過類指標到類記憶體中 去找,但是當它們找到之後,就會在自己的記憶體空間開闢一塊空間來儲存對這個靜態欄位修改後的結果。所以,這個時候類中的靜態欄位就不會被改變,而兩個對象 中的money欄位也就不會互相影響了。
這個時候我們在剛剛的基礎上再加上一段代碼,來看執行的結果,我們發現這個時候再使用類變數對類的靜態變數進行修改,分別看看類和對象中這個變 量的變化,我們發現對象中的變數沒有按照我們期待的那樣發生改變,這也驗證了我們的猜想,因為這個時候對象的記憶體中已經有了money變數,它們就不願意 捨近求遠的到類記憶體中去取變數來給我們顯示了。
#!/usr/bin/env python#-*-coding:utf-8-*-__author__ = ‘Eva_J‘class father(object): #靜態欄位 money = 10000 def __init__(self,name): #普通欄位 self.name = name#類的執行個體化,分別執行個體化出了兩個對象father_obj1,father_obj2father_obj1 = father(‘obj1‘)father_obj2 = father(‘obj2‘)#類調用print ‘father.money:‘,father.money#對象調用print ‘father_obj1.money:‘,father_obj1.moneyprint ‘father_obj2.money:‘,father_obj2.money#使用類調用修改father.money = father.money + 1000print ‘father.money:‘,father.moneyprint ‘father_obj1.money:‘,father_obj1.moneyprint ‘father_obj2.money:‘,father_obj2.money#使用對象調用修改father_obj1.money = father_obj1.money + 1father_obj2.money = father_obj2.money + 2print ‘father.money:‘,father.moneyprint ‘father_obj1.money:‘,father_obj1.moneyprint ‘father_obj2.money:‘,father_obj2.moneyfather.money = father.money + 66print ‘father.money:‘,father.moneyprint ‘father_obj1.money:‘,father_obj1.moneyprint ‘father_obj2.money:‘,father_obj2.moneydemo Code
但是,我們變數類型轉乘字典試試看,結果又不一樣了,代碼在下面,自己粘回去執行吧,這裡就不給你們貼花花綠綠的圖了:
#!/usr/bin/env python#-*-coding:utf-8-*-__author__ = ‘Eva_J‘class father(object): #靜態欄位 money = {‘money‘:10000} def __init__(self,name): #普通欄位 self.name = name#類的執行個體化,分別執行個體化出了兩個對象father_obj1,father_obj2father_obj1 = father(‘obj1‘)father_obj2 = father(‘obj2‘)#類調用print ‘father.money:‘,father.money[‘money‘]#對象調用print ‘father_obj1.money:‘,father_obj1.money[‘money‘]print ‘father_obj2.money:‘,father_obj2.money[‘money‘]#使用類調用修改father.money[‘money‘] = father.money[‘money‘] + 1000print ‘father.money:‘,father.money[‘money‘]print ‘father_obj1.money:‘,father_obj1.money[‘money‘]print ‘father_obj2.money:‘,father_obj2.money[‘money‘]#使用對象調用修改father_obj1.money[‘money‘] = father_obj1.money[‘money‘] + 1father_obj2.money[‘money‘] = father_obj2.money[‘money‘] + 2print ‘father.money:‘,father.money[‘money‘]print ‘father_obj1.money:‘,father_obj1.money[‘money‘]print ‘father_obj2.money:‘,father_obj2.money[‘money‘]father.money[‘money‘] = father.money[‘money‘] + 66print ‘father.money:‘,father.money[‘money‘]print ‘father_obj1.money:‘,father_obj1.money[‘money‘]print ‘father_obj2.money:‘,father_obj2.money[‘money‘]demo Code
偷懶的同學看這裡→_→ :我們只需要記住,在使用類的靜態變數的時候,必須要用類名來調用和修改。它才會永遠被類和對象共用。
從類的繼承這個角度來看看靜態欄位
剛剛我們已經知道了對象和類中靜態欄位的儲存及調用過程,下面我們就從類的繼承這個角度來看看靜態欄位:
1 #!/usr/bin/env python 2 #-*-coding:utf-8-*- 3 __author__ = ‘Eva_J‘ 4 class father(object): 5 6 #靜態欄位 7 money = 10000 8 def __init__(self,name): 9 10 #普通欄位11 self.name = name12 13 class Son1(father):14 pass15 16 class Son2(father):17 pass18 19 class GrandSon(Son1,Son2):20 pass21 22 print ‘father.money : ‘,father.money23 print ‘Son1.money : ‘,Son1.money24 print ‘Son2.money : ‘,Son2.money25 print ‘GrandSon.money : ‘,GrandSon.money26 print ‘*‘*2527 father.money += 100028 print ‘father.money : ‘,father.money29 print ‘Son1.money : ‘,Son1.money30 print ‘Son2.money : ‘,Son2.money31 print ‘GrandSon.money : ‘,GrandSon.money32 print ‘*‘*2533 Son1.money += 10034 Son2.money += 20035 print ‘father.money : ‘,father.money36 print ‘Son1.money : ‘,Son1.money37 print ‘Son2.money : ‘,Son2.money38 print ‘GrandSon.money : ‘,GrandSon.money39 print ‘*‘*2540 GrandSon.money += 141 print ‘father.money : ‘,father.money42 print ‘Son1.money : ‘,Son1.money43 print ‘Son2.money : ‘,Son2.money44 print ‘GrandSon.money : ‘,GrandSon.money45 print ‘*‘*2546 father.money += 200047 print ‘father.money : ‘,father.money48 print ‘Son1.money : ‘,Son1.money49 print ‘Son2.money : ‘,Son2.money50 print ‘GrandSon.money : ‘,GrandSon.money51 52 demoCode
上面這段代碼的執行結果是這樣的:
原理在下面,當我們使用建立類的時候,每個基類和衍生類別都會產生自己的記憶體,一開始衍生類別中沒有money變數,所以在調用的時候它們通過類中 維護的指標都順利地找到了父類中的money變數,返回給了我們,但是當我們使用 衍生類別名.靜態欄位名 對衍生類別中的靜態欄位進行修改的時候,它們就默默地把修改的結果存在了自己的記憶體空間內。所以在之後的調用中就不千裡迢迢的去父類中找這個變數了。其實和 上面的道理是一樣一樣噠!
偷懶的同學看這裡→_→ :我們只需要記住,在使用類的靜態變數的時候,如果我們希望基類和各衍生類別的靜態欄位被共用,必須要用基類名來調用和修改。
到這裡關於類的靜態欄位的內容就全部講完了,簡簡單單的一個靜態欄位,竟然囊括了這麼多知識點,是不是值得我們花一點點時間來搞清楚呢?
python的類和對象(類的靜態欄位)