轉自:http://www.cnblogs.com/Eva-J/p/5044411.htmlhtml
什麼是靜態字段python
在開始以前,先上圖,解釋一下什麼是類的靜態字段(我有的時候會叫它類的靜態變量,總之說的都是它。後面大多數狀況可能會簡稱爲類變量。):ide
咱們看上面的例子,這裏的money就是靜態字段,首先看它的位置,是在father類中,而不是在__init__中。那麼一個小小的靜態字段,我爲何要特地寫一篇番外給它呢?耐着性子看下去,你就會發現一個小小的類變量,卻折射出了整個類的世界。spa
首先咱們先來解釋一下什麼叫作靜態字段:3d
咱們看上面的例子,左中右三張圖,左邊是純淨的代碼,中間是我給代碼加上的內存加載過程,右邊是執行結果。咱們在這裏先看中間的圖,來看這個文件加載的過程。指針
1.將類存入了內存 2.將money變量放入了內存 3.將__init__方法的地址放入了內存code
接下來咱們執行了一個__dict__方法,咱們看右邊圖中現實的執行結果,發現這個時候內存中已經存入了money這個變量,它隨着這個程序 的執行產生,隨着程序的結束而消失,這樣和程序‘共存亡’的字段,咱們就叫它靜態字段。它就像是一個全局變量,不屬於任何一個對象,咱們能夠直接使用類來 調用,也能夠在對象使用方法的時候使用它。它是對象共享的變量,存在類的內存裏。htm
靜態字段的調用方法對象
剛剛咱們知道了什麼是靜態字段,如今咱們就來看看靜態字段是怎麼使用的?blog
上面給出了兩種使用方式,類調用和對象調用,哎?看起來好像能夠哎!咱們再來修改一下類變量瞧瞧:
咱們看,當咱們使用 類名.靜態字段名 修改類變量以後,使用類或者對象去調用這個靜態字段,發現它們都產生了變化。好像一切都在咱們的預料之中哎,這樣的話對象和類均可以使用類變量的樣子!若是大家真的信了那就太天真了。。。看看下面這個例子:
看上面的圖,我是接着上面的例子寫的,黃框框裏是我加上的內容,咱們結果中最後打印出來的內容,哎?咱們看到了什麼?好像對象調用的類變量只是 針對各自的對象發生了改變,並無改變類中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_obj2 father_obj1 = father('obj1') father_obj2 = father('obj2') #類調用 print 'father.money:',father.money #對象調用 print 'father_obj1.money:',father_obj1.money print 'father_obj2.money:',father_obj2.money #使用類調用修改 father.money = father.money + 1000 print 'father.money:',father.money print 'father_obj1.money:',father_obj1.money print 'father_obj2.money:',father_obj2.money #使用對象調用修改 father_obj1.money = father_obj1.money + 1 father_obj2.money = father_obj2.money + 2 print 'father.money:',father.money print 'father_obj1.money:',father_obj1.money print 'father_obj2.money:',father_obj2.money father.money = father.money + 66 print 'father.money:',father.money print 'father_obj1.money:',father_obj1.money print 'father_obj2.money:',father_obj2.money demo 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_obj2 father_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'] + 1000 print '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'] + 1 father_obj2.money['money'] = father_obj2.money['money'] + 2 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'] + 66 print '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 = name 12 13 class Son1(father): 14 pass 15 16 class Son2(father): 17 pass 18 19 class GrandSon(Son1,Son2): 20 pass 21 22 print 'father.money : ',father.money 23 print 'Son1.money : ',Son1.money 24 print 'Son2.money : ',Son2.money 25 print 'GrandSon.money : ',GrandSon.money 26 print '*'*25 27 father.money += 1000 28 print 'father.money : ',father.money 29 print 'Son1.money : ',Son1.money 30 print 'Son2.money : ',Son2.money 31 print 'GrandSon.money : ',GrandSon.money 32 print '*'*25 33 Son1.money += 100 34 Son2.money += 200 35 print 'father.money : ',father.money 36 print 'Son1.money : ',Son1.money 37 print 'Son2.money : ',Son2.money 38 print 'GrandSon.money : ',GrandSon.money 39 print '*'*25 40 GrandSon.money += 1 41 print 'father.money : ',father.money 42 print 'Son1.money : ',Son1.money 43 print 'Son2.money : ',Son2.money 44 print 'GrandSon.money : ',GrandSon.money 45 print '*'*25 46 father.money += 2000 47 print 'father.money : ',father.money 48 print 'Son1.money : ',Son1.money 49 print 'Son2.money : ',Son2.money 50 print 'GrandSon.money : ',GrandSon.money 51 52 demoCode
上面這段代碼的執行結果是這樣的:
原理在下面,當咱們使用建立類的時候,每一個基類和派生類都會產生本身的內存,一開始派生類中沒有money變量,因此在調用的時候它們經過類中 維護的指針都順利地找到了父類中的money變量,返回給了咱們,可是當咱們使用 派生類名.靜態字段名 對派生類中的靜態字段進行修改的時候,它們就默默地把修改的結果存在了本身的內存空間內。因此在以後的調用中就不千里迢迢的去父類中找這個變量了。其實和 上面的道理是同樣同樣噠!
偷懶的同窗看這裏→_→ :咱們只須要記住,在使用類的靜態變量的時候,若是咱們但願基類和各派生類的靜態字段被共享,必需要用基類名來調用和修改。
到這裏關於類的靜態字段的內容就所有講完了,簡簡單單的一個靜態字段,居然囊括了這麼多知識點,是否是值得咱們花一點點時間來搞清楚呢?