雙下劃線
感謝018.11.25
我發現公司裡即便是工作經驗一年的程式設計師依然對python的私有屬性有些迷糊——也就是下劃線的問題——拿捏不准要怎麼用。我想在此總結一下。
前置單下劃線是一種約定,即:認為這個變數或方法是類私有,外界不要呼叫。在這裡,物件認為是「外界」。
示例如下:
class
persion
(object):
def__init__
(self, name, age, hobbies)
:# 不建議被外界使用
self._name = name
self._age = age
self._hobbies = hobbies
# 允許被外界呼叫
@property
defdetail
(self)
:return self._get_sentence(
)# 建議不要被外界呼叫,而是在類中使用
def_get_sentence
(self)
:return f" is and loves ."
if __name__ ==
"__main__"
: lily = persion(
"lily",18
,"listenning"
)print
(lily.detail)
# 輸出:
# lily is 18 and loves listenning.
但外界能不能呼叫帶前置單下劃線的成員變數和成員方法呢?事實上是可以的:
print
(lily._name)
# 輸出:lily
print
(lily._get_sentence())
# 輸出: lily is 18 and loves listening.
我實在記不清是《python程式設計之美》還是《資料結構(python描述)》,裡面對此解釋說:之所以python對類私有只是一種約定,是認為使用python開發的程式設計師應該是成熟的。
而另一方面,在乙個模組中,前置單下劃線的變數或是函式,不能通過from module import *
方式匯入。如:
# demo1.py
# 這是乙個變數
_one =
"one"
# 這是乙個函式
def_two()
:print
("two"
)
# demo2.py
from demo1 import
*print
(_one)
# 錯誤使用
_two(
)# 錯誤使用
對此直譯器會丟擲異常:nameerror: name '***' is not defined
。
但並非demo1中的前置單下劃線變數/方法在demo2中就不可以使用,完全可以import module
,然後通過module.***
方式,demo2**做如下調整:
# demo2.py
import demo1
print
(demo1._one)
# 正確使用
demo1._two(
)# 正確使用
後置單下劃線是一種程式設計風格建議,即:當你的變數/方法名與python中的關鍵字衝突時,可以加上後置單下劃線做區分。如:
list_ =
["lily"
,"bob"
,"green"
]dict_ =
事實上,前置雙下劃線變數/方法,更像是類私有。將第乙個示例**改寫如下(單下劃線都改寫為雙下劃線):
class
persion
(object):
def__init__
(self, name, age, hobbies)
:# 不能被外界訪問
self.__name = name
self.__age = age
self.__hobbies = hobbies
# 允許被外界呼叫
@property
defdetail
(self)
:return self.__get_sentence(
)# 不能被外界呼叫
def__get_sentence
(self)
:return f" is and loves ."
if __name__ ==
"__main__"
: lily = persion(
"lily",18
,"listening"
)print
(lily.detail)
# 輸出:
# lily is 18 and loves listening.
可如果你想外界訪問:
print
(lily.__name)
# 錯誤示例
print
(lily.__get_sentence())
# 錯誤示例
直譯器會拋異常:attributeerror: 'persion' object has no attribute '__name'
。
其實同前置單下劃線一樣,雙下劃線其實也可以被外界訪問,只不過直譯器對他們**「以類之姓,冠它之名」**。
print
(lily._persion__name)
# 輸出:lily
lily._persion__get_sentence(
)# 輸出:lily is 18 and loves listening.
也就是說,當類名為x
,雙下劃線變數為__y
時,外界對其訪問應該形如:_x__y
。
完全與前置單下劃線一樣的是,模組中的前置雙下劃線變數/函式,不能通過from module import *
匯入,但可以import module
後使用:
module.__one
module.__two(
)
前置雙下劃線存在的意義:為了避免該成員的名稱與子類中的名稱衝突。
開個玩笑。
後置雙下劃線既沒有實際意義,也不是程式設計風格的建議。
稍微對python熟悉的人就會知道,存在前置雙下劃線同時還有後置雙下劃線的變數以及方法。如常見的__name__
以及__init__()
。這些屬於python的魔法物件,是為了區別其他使用者自定義的命名。官方表示:永遠不要將這樣的命名方式應用於自己的變數或函式。
Python中單下劃線和雙下劃線
python中存在一些特殊的方法,有些方法以雙下劃線 開頭和結尾,它們是python的魔法函式,比如 init 和 str 等等。不用要這種方式命名自己的變數或者函式。class a def init self,text self.text text def str self return self...
Python中單下劃線和雙下劃線
雙下劃線開頭和結尾 python中存在一些特殊的方法,有些方法以雙下劃線 開頭和結尾,它們是python的魔法函式,比如 init 和 str 等等。不用要這種方式命名自己的變數或者函式。classa def init self,text self.text text def str self re...
python中單下劃線 和雙下劃線(
函式使用單下劃線 開頭 使用單下劃線 開頭的函式 func不能被模組外部以 from module www.cppcns.comimport 形式匯入。但程式設計客棧可以用 from module import func形式單獨匯入。類屬性和類方法使用單下劃線 開頭 開頭為保護型別的屬性和方法,僅允...