Python下劃線和私有變量
最近小組python氛圍濃厚,有同學發現自己在一個類裏定義了一個方法,但不能用getattr調用。我整理一下python中下劃線在命名時的特殊用法。
規範描述
根據PEP-0008的規範:
In addition, the following special forms using leading or trailing
underscores are recognized (these can generally be combined with any
case convention):
_single_leading_underscore
: weak “internal use” indicator.
E.g.from M import *
does not import objects whose name starts
with an underscore.
single_trailing_underscore_
: used by convention to avoid
conflicts with Python keyword, e.g. ::Tkinter.Toplevel(master, class_='ClassName')
__double_leading_underscore
: when naming a class attribute,
invokes name mangling (inside class FooBar,__boo
becomes
_FooBar__boo
; see below).
__double_leading_and_trailing_underscore__
: “magic” objects or attributes that live in user-controlled namespaces.
E.g.__init__
,__import__
or__file__
. Never invent
such names; only use them as documented.
是的,python中下劃線在命名時是有規範的。下面分別舉例說明。
單下劃線開頭
單下劃線開頭的命名,規範裏描述爲“弱內部引用”,一般對應“protect”。
##m.py
a = 1
_a = 2
__a = 3
##test.py
import m
from m import *
print a # 打印1
print _a # 異常,NameError: name '_a' is not defined
print m.a # 打印1
print m._a # 打印2
import *時不能導入單下劃線開頭命名的變量或方法。訪問的時候可以通過“模塊.變量”。這裏的protect並非嚴格的。
##c.py
class C(object):
a = 1
_a = 2
## test.py
from c import C
o = C()
print o.a #打印1
print o._a #打印2
o._a = 3
print o._a #打印3
我們可以看到類中_a也是可以通過對象直接訪問的。這裏的“protect”是一種規範,我們應該按照規範來編寫代碼。
單下劃線結尾
單下劃線結尾的命名用來與python中有保留字段避免衝突,pep8給的例子
Tkinter.Toplevel(master, class_='ClassName')
雙下劃線開頭
雙下滑線開頭被認爲是私有的。python中的private並非像C++中那樣嚴格定義,而是通過改編命名,將雙下滑線開頭的命名前面加上單下劃線+類名。
##c.py
class C(object):
a = 1
_a = 2
__a = 3
##test.py
from c import C
o = C()
print o.a #打印1
print o._a #打印2
print o.__a #異常,AttributeError: 'C' object has no attribute '__a'
print o._C__a #打印3
所以,雙下劃線開頭的命名用getattr(“__xxx”)是獲取不到的,但是用getattr(“_Class__xxx”)就可以訪問。不過這裏還是要提一個規範的問題。既然我們用雙下劃線開頭,就是希望作爲一個私有的變量或方法。那我們應該用私有的用法去使用。
雙下劃線開頭、雙下劃線結尾
像__init__,__new__,這種,作爲python class的特殊用法專用的標識,就不多舉例了。