2014-04-26 49 views
9

我以爲他們是同之前我跑這個代碼:getattr(self,'__a')和self .__ a在Python中有什麼區別?

class B(object): 
    def show(self): 
     self.__a = "test" 
     print "B" 

    def this_b(self): 
     print "this_b" 
     print self.__a 
     print getattr(self, '__a') #exception 


class C(B): 
    def show(self): 
     print "C" 
     # B.show(self) 
     super(C, self).show() 


    def call(self): 
     print "call" 
     self.show() 
     self.this_b() 
     # print self.__a 

C().call() 

它提高AttributeError: 'C' object has no attribute '__a'getattr語句,但爲什麼呢?

+3

因爲[名稱重整(https://docs.python.org/2/tutorial/classes.html#私有變量和一流的本地引用)。 – nneonneo

+0

通常,現在在Python中不鼓勵使用'__'前綴的屬性名稱,而只使用一個下劃線。 –

+2

@ErikAllik:我不確定這是否受到鼓勵。它始終只適用於在派生類中應該防止意外覆蓋的變量。 – nneonneo

回答

9

這是因爲Private name mangling

私人名稱重整:當該文本上發生在類定義的標識符開始於兩個或多個下劃線字符,並在兩個或多個下劃線並沒有結束,則認爲類的專用名稱。在爲其生成代碼之前,專用名稱會轉換爲更長的形式。該轉換將在名稱前插入類名,並刪除前導下劃線和插入的單個下劃線。例如,名爲Ham的類中出現的標識符__spam將轉換爲_Ham__spam。這種轉換獨立於使用標識符的語法上下文。如果轉換的名稱非常長(超過255個字符),則可能會發生實現定義的截斷。如果類名只包含下劃線,則不進行轉換。

當你

self.__a 

私人名字改編會自動照顧。但是,當你做

print getattr(self, '__a') 

你必須做手工,這樣

print getattr(self, '_B__a') 
# test 
+1

不錯的解釋! – LeoShi

相關問題