python 裡面的單下劃線與雙下劃線的區別

2021-07-10 09:09:12 字數 4561 閱讀 6686

主要存在四種命名

1.

object # 公用方法

2. __object__ # 內建方法,使用者不要這樣定義

3. __object # 全私有,全保護

4. _object # 半保護

核心風格:避免用下劃線作為變數名的開始。

因為下劃線對直譯器有特殊的意義,而且是內建識別符號所使用的符號,我們建議程式設計師避免用下劃線作為變數名的開始。一般來講,變數名_object被看作是「私有的」,在模組或類外不可以使用,不能用』from module import *』匯入。當變數是私有的時候,用_object來表示變數是很好的習慣。

單下劃線+類名,eg:_class__object機制就可以訪問__object__了。因為變數名__object__對python 來說有特殊含義,對於普通的變數應當避免這種命名風格。

「單下劃線」 開始的成員變數叫做保護變數,意思是只有類物件和子類物件自己能訪問到這些變數;」雙下劃線」 開始的是私有成員,意思是只有類物件自己能訪問,連子類物件也不能訪問到這個資料。(如下列所示)

以單下劃線開頭_foo的代表不能直接訪問的類屬性,需通過類提供的介面進行訪問,不能用「from *** import *」而匯入;以雙下劃線開頭的__foo代表類的私有成員;以雙下劃線開頭和結尾的__foo__代表python裡特殊方法專用的標識,如__init__()代表類的建構函式。

class

foo():

def__init__

(): ...

defpublic_method

():print

'this is public method'

def__fullprivate_method

():print

'this is fullprivate_method'

def_halfprivate_method

():print

'this is halfprivate_method'

f = foo()

f.public_method() # ok

f.__fullprivate_method() # error occur

f._halfprivate_method() # ok

f._foo__fullprivate_method() # ok

從上面的例子可以看出,f._halfprivate_method()可以直接訪問,確實是。不過根據python的約定,應該將其視作private,而不要在外部使用它們,(如果你非要使用也沒轍),良好的程式設計習慣是不要在外部使用它。同時,根據python docs的說明,_object和__object的作用域限制在本模組內。

class

a(object):

def__init__

(self):

self.__private()

self.public()

def__private

(self):

print

'a.__private()'

defpublic

(self):

print

'a.public()'

class

b(a):

def__private

(self):

print

'b.__private()'

defpublic

(self):

print

'b.public()'

b = b()

初探

正確的答案是:

a.__private()

b.public()

我們分別看下類a和類b的屬性都有哪些:

>>> print '\n'.join(dir(a))

_a__private

__init__

public

>>> print '\n'.join(dir(b))

_a__private

_b__private

__init__

public

為什麼類a有個名為_a__private的 屬性呢?而且__private消失了!這就要談談python的私有變數「矯直」了。

python把以兩個或以上下劃線字元開頭且沒有以兩個或以上下劃線結尾的變數當作私有變數。私有變數會在**生成之前被轉換為長格式(變為公有)。轉換機制是這樣的:在變數前端插入類名,再在前端加入乙個下劃線字元。這就是所謂的私有變數矯直(private name mangling)。如類 a裡的__private識別符號將被轉換為_a__private,這就是上一節出現_a__private__private消失的原因了。

再講兩點題外話:

一是因為矯直會使識別符號變長,當超過255的時候,python會切斷,要注意因此引起的命名衝突。

二是當類名全部以下劃線命名的時候,python就不再執行矯直。如:

class

____

(object):

def__init__

(self):

self.__method()

def__method

(self):

print

'____.__method()'

print

'\n'.join(dir(____))

__class__

__delattr__

__dict__

__doc__

__getattribute__

__hash__

__init__

__method # 沒被矯直

__module__

__new__

__reduce__

__reduce_ex__

__repr__

__setattr__

__str__

__weakref__

obj = ____()

____.__method()

obj.__method() # 可以外部呼叫

____.__method()

現在我們回過頭來看看為什麼會輸出「a.__private()」吧!

矯直之後,類a的**就變成這樣了:

class

a(object):

def__init__

(self):

self._a__private() # 這行變了

self.public()

def_a__private

(self):

# 這行也變了

print

'a.__private()'

defpublic

(self):

print

'a.public()'

因為在類b定義的時候沒有覆蓋__init__方法,所以呼叫的仍然是a.__init__,即執行了self._a__private(),自然輸出「a.__private()」了。

下面的兩段**可以增加說服力,增進理解:

class

c(a):

def__init__

(self):

# 重寫 __init__ ,不再呼叫self._a__private

self.__private()# 這裡繫結的是 _c_private

self.public()

def__private

(self):

print

'c.__private()'

defpublic

(self):

print

'c.public()'

c = c()

答案:c.__private()

c.public()

class

a(object):

def__init__

(self):

self._a__private() # 呼叫乙個沒有定義的函式,但可執行

self.public()

def__private

(self):

print

'a.__private()'

defpublic

(self):

print

'a.public()'

a = a()

答案:a.__private()

a.public()

python 裡面的單下劃線與雙下劃線的區別

python 用下劃線作為變數字首和字尾指定特殊變數。不能用 from moduleimport 匯入 系統定義名字 類中的私有變數名 核心風格 避免用下劃線作為變數名的開始。因為下劃線對直譯器有特殊的意義,而且是內建識別符號所使用的符號,我們建議程式設計師避免用下 劃線作為變數名的開始。一般來講,...

python 裡面的單下劃線與雙下劃線的區別

python 用下劃線作為變數字首和字尾指定特殊變數。不能用 from moduleimport 匯入 系統定義名字 類中的私有變數名 核心風格 避免用下劃線作為變數名的開始。因為下劃線對直譯器有特殊的意義,而且是內建識別符號所使用的符號,我們建議程式設計師避免用下 劃線作為變數名的開始。一般來講,...

python 裡面的單下劃線與雙下劃線的區別

python 用下劃線作為變數字首和字尾指定特殊變數。不能用 from moduleimport 匯入 系統定義名字 類中的私有變數名 核心風格 避免用下劃線作為變數名的開始。因為下劃線對直譯器有特殊的意義,而且是內建識別符號所使用的符號,我們建議程式設計師避免用下 劃線作為變數名的開始。一般來講,...