沙師弟學Python之 _, __ 和 __xx__的區別

正版沙師弟發表於2019-04-10

這幾天本菜鳥在學習資料結構與演算法,學習資料結構與演算法免不了要手動實現這些資料結構與演算法。在用類定義這些物件的時候,發現老是出現帶有 _ ,__ 和__xx__ 的函式,一開始也沒怎麼在意,想著這些也學過,但是今天仔細思考一下這些用法與區別,才發現已經忘的七七八八了,就這樣好奇心逼著我去找出他們的區別。閱讀了幾篇部落格之後,本菜鳥知道了這三兄弟的區別。

1. "_" 單下劃線

Python中是不存在真正的私有方法的,但是為了實現類似於c++中的私有方法,於是就在類的方法或者屬性前加一個“_”,意味著該方法或者屬性就不應該被呼叫了。

class A(object):
    def _test(self):
        print("這個函式不應該通過_tset呼叫,而應該通過test呼叫")

    def test(self):
        return self._test()


a = A()
a._test()
a.test()
複製程式碼

結果

這個函式不應該通過_tset呼叫,而應該通過test呼叫
這個函式不應該通過_tset呼叫,而應該通過test呼叫
複製程式碼

由此可得,這個方法是能被呼叫的,但出於某種約定,我們是一般不去呼叫的。

2. “__” 雙下劃線

雙下劃線表示的是私有型別的變數,既然是私有了,那肯定就不允許子類訪問了,只允許這個類(self)自身訪問。

class A(object):
    def __test(self):
        print("I am test in A")

    def test(self):
        return self.__test()


a = A()
a.test()
複製程式碼

結果:

I am test in A
複製程式碼

返回的結果是我們預料之中的。


接著,我們給A新增一個子類,並重新定義它的__test()方法。

class B(A):
    def __test(self):
        print("I am test in B")


b = B()
b.test()
複製程式碼

現在,結果是這樣的:

I am test in A
複製程式碼

可見,子類B重新定義之後的__test()返回的依然是A類中的__method(),由此我們可以知道以“__"開頭的方法是不能被重寫的,只允許在內部使用

"__ xx __" 前後雙下劃線

這種方法被稱為magic methods(魔術方法),一般是系統定義名字,類似於__init__(),一般是給Python呼叫的。

class WrongMethod(object):
    def __init__(self, n):
        self.n = n

    def __add__(self, other):
        return self.n - other

    def __sub__(self, other):
        return self.n + other

    def __str__(self):
        return str(self.n)


num = WrongMethod(20)
print("num = ", num)
print("num + 10 = ", num + 10)
print("num - 10 = ", num - 10)
複製程式碼

結果

num =  20
num + 10 =  10
num - 10 =  30
複製程式碼

上面的例子就能比較好的提現出來,"__ xx __" 這種方法一般是Python呼叫的。

結論

  1. ”_“ 是私有的,一般不應該被呼叫
  2. ”__“ 是為了避免子類重寫某個函式而使用的
  3. ”__ xx __“ 一般是用於Python呼叫

相關文章