Python 的 underscore 和 hidden object
嚴格來說,python 並沒有 private 的概念
如果要把一個東西做 hidden,建議用一個 underscore 好
兩個 underscore 會 trigger 一個叫 name mangling (mangle: 軋壓) 的動作
詳細的底線介紹請看:
到底是在__底線__什麼啦
在課堂上以哲給的範例裡:
=============
showhidden和doubleline同樣都是定義在父類別裡面
但是在 子類別裡面的showhidden
1. 先去抓子類別新定義出來的 _string, 結果是 Grape,
2. 再去找_string2,因為子類別沒有定義新的 _string2,所以去父類別抓,結果是 Durian。
然而子類別的 doubleline 抓的完全是父類別的變數,就算子類別也有自己的 __string,他不管。
如果要把一個東西做 hidden,建議用一個 underscore 好
兩個 underscore 會 trigger 一個叫 name mangling (mangle: 軋壓) 的動作
詳細的底線介紹請看:
到底是在__底線__什麼啦
在課堂上以哲給的範例裡:
=============
class FirstClass: string = "Apple" __string = "Banana" def fun(self, language = None): if language is not None: print (language + " : Hello World!") else: print("Hello World!") def __notfun(self): print("Learn Python") def showhidden(self): self.__notfun() class SecondClass(FirstClass): def duringclass(self): print("eating " + self.string) def afterclass(self): print("eating " + self.__string) def __notfun(self): super().__notfun() print("Write code") ============================== 如果執行: my_class = SecondClass() my_class.afterclass()
會出現error
AttributeError: 'SecondClass' object has no attribute '_SecondClass__string'
原因是,如果用2個底線,在解讀時 python 會強迫解讀成 _當前的class__string
但是當前的class沒有__string這個變數
所以出現error
如果要在 firstclass 產生一個 hidden attribute,令 secondClass 也可以使用
請用一個underscore就好。
==============================
為了更深入解釋上面 name mangling 的概念,我改了一下程式
====
class FirstClass:
string = "Apple"
_string = "Orange"
_string2= "Grava"
__string = "Banana"
__string2 = "Durian"
def doubleline(self):
print('The __string is ', self.__string)
print('The __string2 is ', self.__string2)
def showhidden(self):
print('the hidden _string is ', self._string)
print('the hidden _string2 is ', self._string2)
class SecondClass(FirstClass):
_string = "Grape"
__string = "mango"
def doubleline2(self):
print("The __string is " + self.__string)
print("The __string2 is " + self.__string2)
=============
在 FirstClasss 裡面
my_obj.doubleline()
The __string is Banana
The __string2 is Durian
my_obj.showhidden()
the hidden _string is Orange
the hidden _string2 is Grava
===
另外, 在 SecondClass 裡面:
my_class = SecondClass()
my_class.showhidden()
the hidden _string is Grape
the hidden _string2 is Grava
my_class.doubleline()
The __string is Banana
The __string2 is Durian
my_class.doubleline2()
The __string is mango
Traceback (most recent call last):
File "<ipython-input-50-eb64d22ea2c3>", line 1, in <module>
my_class.doubleline2()
File "<ipython-input-43-044dc11a7d6f>", line 25, in doubleline2
print("The __string2 is " + self.__string2)
AttributeError: 'SecondClass' object has no attribute '_SecondClass__string2'
看出差別了嗎?showhidden和doubleline同樣都是定義在父類別裡面
但是在 子類別裡面的showhidden
1. 先去抓子類別新定義出來的 _string, 結果是 Grape,
2. 再去找_string2,因為子類別沒有定義新的 _string2,所以去父類別抓,結果是 Durian。
然而子類別的 doubleline 抓的完全是父類別的變數,就算子類別也有自己的 __string,他不管。
因為 doubleline 在父類別裡方法生成時,就指定是抓父類別的 __string。
最後新的 doubleline2,方法裡指定的是 self.__string 和 self.__string2,
所以只會在自己(子)的類別裡抓這兩個變數,
結果 __string = mango
但是 __string2 在子類別沒有定義,所以出現 error。
【參考資料】
前後單雙底線的解釋:
最後新的 doubleline2,方法裡指定的是 self.__string 和 self.__string2,
所以只會在自己(子)的類別裡抓這兩個變數,
結果 __string = mango
但是 __string2 在子類別沒有定義,所以出現 error。
【參考資料】
前後單雙底線的解釋:
https://aji.tw/python%E4%BD%A0%E5%88%B0%E5%BA%95%E6%98%AF%E5%9C%A8__%E5%BA%95%E7%B7%9A__%E4%BB%80%E9%BA%BC%E5%95%A6/
雙底線在 python class 裡的意涵:
https://stackoverflow.com/questions/1301346/what-is-the-meaning-of-a-single-and-a-double-underscore-before-an-object-name
這個人遇到了和我們類似的問題,回覆的人給了一樣的答覆:
https://stackoverflow.com/questions/17947250/python-hide-member-of-base-class-in-derived-class
留言
張貼留言