2017-10-18 135 views
0

這裏瓦爾一個小例子代碼:困惑靜態類在python

class A: 
    staticvar=3; 

    def foo2(self): 
     print("------ Foo2") 
     print("static: "+str(A.staticvar)); 
     print("instance: "+ str(self.staticvar)); 

class B(A): 

    def setStaticVar(self, num): 
     B.staticvar=num; 


a=A(); 
b=B(); 

a.staticvar=7; 
a.foo2(); 

b.setStaticVar(100); 

a.foo2(); 

b.foo2(); 

什麼結果:

------ 
static: 3 
instance: 7 -->correct. Instance var modified 
------ 
static: 3 
instance: 7 --> Not correct. Why static var is not 100 
------ 
static: 3 
instance: 100 --> Correct, but this value should be shared between A and B 

這究竟是爲什麼? A和B之間不應該共享靜態變量?爲什麼當它在b到b中被修改時。從這個例子看來,每個類都有自己的靜態變量(從我的角度來看,並不是真正的靜態變量,因爲只有一個靜態變量,而且每個類只有一個靜態變量)。

任何人都可以解釋這種行爲?

乾杯。

回答

0

我懷疑你遇到的是名稱解析問題。當你得到B.staticvar時,解釋器無法找到它並退回到它的超類以嘗試解析名稱。在遍歷到A後,解釋器找到staticvar並返回該值。

當您設置一個值,B.staticvar,但是,你會得到許多相同的行爲,你的「實例」的情況下,其中一個屬性調用staticvar添加到B。現在,當它試圖解析B(或其實例)上的屬性名稱時,它將使用這個新值,而不會回落到A。在Python中,繼承一個類沒有太多關於共享它的屬性的知識,它是關於設置一個fallback類來解析名稱,當它們沒有在你的子類中定義時(因此爲什麼不需要明確地「覆蓋」方法,以及爲什麼你必須記得在B.method_name內調用super(A).method_name,如果你想要運行父功能)。

爲了得到你要求的行爲,無論是在A定義setStaticVar,和/或改變其身體A.staticvar=num

+0

又是怎樣呢,那只有一個靜態無功的類可以通過A.被accesed類中的staticvar或self.staticvar?不應該在使用print(self.staticvar)時拋出錯誤,因爲它無法解析實例var? – Notbad

+1

類實例上的名稱解析從實例上開始,但後來回到類本身。例如,類的方法在類中定義,而不在其實例上定義,但可以在實例上調用它們。例如,給定'a = A()','a.setStaticVar(5)'解析爲'A.setStaticVar(a,5)',實際上你可以寫第二行,它的行爲就是相同。同樣,'staticvar'存在於'A'中,可以通過'a'訪問,或者可以通過定義具有相同名稱的'a'的屬性來映射。 – scnerd

+1

一般來說,在像Python這樣的動態類型語言中(我相信JS和類似語言也同樣適用),純粹用名稱與值之間的映射關係來考慮「類」和「實例」與備份樹如果名字在任何給定點都不能解決,你可以去。對象,類型,模塊,甚至本地上下文(閉包)都只是可以嵌套在彼此之內的字典。你可以玩遊戲來修改各種級別的字典,但對這種語言中的「靜態」變量沒有太多的想法。 – scnerd