Python封裝底層實現原理詳解(通俗易懂)

2020-07-16 10:05:19
事實上,Python 封裝特性的實現純屬“投機取巧”,之所以類物件無法直接呼叫以雙下劃線開頭命名的類屬性和類方法,是因為其底層實現時,Python 偷偷改變了它們的名稱。

前面章節中,我們定義了一個 CLanguage 類,定義如下:
class CLanguage :
    def setname(self, name):
        if len(name) < 3:
            raise ValueError('名稱長度必須大於3!')
        self.__name = name

    def getname(self):
        return self.__name
    #為 name 設定 setter 和 getter 方法
    name = property(getname, setname)
    def setadd(self, add):
        if add.startswith("http://"):
            self.__add = add
        else:
            raise ValueError('地址必須以 http:// 開頭')

    def getadd(self):
        return self.__add
  
    #為 add 設定 setter 和 getter 方法
    add = property(getadd, setadd)

    #定義個私有方法
    def __display(self):
        print(self.__name,self.__add)
注意,在這個類中,有一個 __display() 方法,由於其是私有方法,且該類沒有提供任何呼叫該方法的“介面”,因此在目前看來,此方法根本無法在類外部呼叫。也就是說,如下呼叫 __display() 方法是不可行的:
clang = CLanguage()
#嘗試呼叫私有的 display() 方法
clang.__display()
這會導致如下錯誤:

Traceback (most recent call last):
  File "D:python3.61.py", line 33, in <module>
    clang.__display()
AttributeError: 'CLanguage' object has no attribute '__display'


那麼,是不是類似 display() 這種的私有方法,真的沒有方法呼叫嗎?如果你深入了解 Python 封裝機制的底層實現原理,就可以呼叫它。

事實上,對於以雙下劃線開頭命名的類屬性或類方法,Python 在底層實現時,將它們的名稱都偷偷改成了 "_類名__屬性(方法)名" 的格式。

就以 CLanguage 類中的 __display() 為例,Python 在底層將其方法名偷偷改成了“_CLanguage__display()”。例如,在 CLanguage 類的基礎上,執行如下程式碼:
clang = CLanguage()
#呼叫name的setname()方法
clang.name = "C語言中文網"
#呼叫add的setadd()方法
clang.add = "http://c.biancheng.net"
#直接呼叫隱藏的display()方法
clang._CLanguage__display()
輸出結果為:

C語言中文網 http://c.biancheng.net


不僅如此,那些原本我們認為是私有的類屬性(例如 __name 和 __add),其底層的名稱也改成了“_類名__屬性名”的這種格式。例如:
clang = CLanguage()
clang.name = "C語言中文網"
clang.add = "http://c.biancheng.net"
#直接呼叫 name 和 add 私有屬性
print(clang._CLanguage__name,clang._CLanguage__add)
執行結果為:

C語言中文網 http://c.biancheng.net

甚至於,我們還可以通過這種方式修改 clang 物件的私有屬性,例如:
clang._CLanguage__name = "Python教學"
clang._CLanguage__add = "http://c.biancheng.net/python"
print(clang._CLanguage__name,clang._CLanguage__add)
輸出結果為:

Python教學 http://c.biancheng.net/python

總結

Python 類中所有的屬性和方法,都是公有(public)屬性,如果希望 Python 底層修改類屬性或者類方法的名稱,以此將它們隱藏起來,只需將它們的名稱前新增雙下劃線(“__”)即可。