以下內容使用Markdown編寫.包括python變量命名規則,特別是私有變量的使用.
問題引入
在編寫orm時候,看到一些參考資料上對變量的命名有些特殊,有的前面有一個下划線,有時會有兩個,很是困惑;本以為變量的命名只要是前面是下划線或字母即可,為了弄清這個問題,產生這個文章 .
命名規范
-
常規變量命名
這里可以[參考資料](4)
-
特殊變量命名
1、 _xx 以單下划線開頭的表示的是protected類型的變量。即保護類型只能允許其本身與子類進行訪問。若內部變量標示,如: 當使用“from M import”時,不會將以一個下划線開頭的對象引入 。
2、 __xx 雙下划線的表示的是私有類型的變量。只能允許這個類本身進行訪問了,連子類也不可以用於命名一個類屬性(類變量),調用時名字被改變(在類FooBar內部,__boo變成_FooBar__boo,如self._FooBar__boo)
3、 xx__定義的是特列方法。用戶控制的命名空間內的變量或是屬性,如__init , import__或是__file 。只有當文檔有說明時使用,不要自己定義這類變量。 (就是說這些是python內部定義的變量名)
在這里強調說一下私有變量,python默認的成員函數和成員變量都是公開的,沒有像其他類似語言的public,private等關鍵字修飾.但是可以在變量前面加上兩個下划線"",這樣的話函數或變量就變成私有的.這是python的私有變量軋壓
(這個翻譯好拗口),英文是(private name mangling
.) **情況就是當變量被標記為私有后,在變量的前端插入類名,再類名前添加一個下划線"",即形成了_ClassName__變量名
.**
實例演示
例子演示
class A(object):
def __init__(self):
self.__private()
self.public()
def __private(self):
print 'A.__private()'
def public(self):
print 'A.public()'
class B(A):
def __private(self):
print 'B.__private()'
def public(self):
print 'B.public()'
a = A() # 實例化對象a
b = B() # 實例化對象b
print a.__private() # 這里會報錯,說 AttributeError: 'a' object has no attribute '__private'
print b.__private() # 這里會報錯,說 AttributeError: 'B' object has no attribute '__private'
print '======'
print b._A__private() # 因為私有變量軋壓機制,__private方法變成_A__private()
print dir(b) # 通過自省方法dir(),查看b所具有的屬性
print '======'
# --->
A.__private()
B.public()
======
A.__private()
======
['_A__private', '_B__private', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_test', 'get_pri', 'public']
類A和B都有一個私有方法,命名為_ _private()
,因為B是繼承於A,在用B實例化對象b時,程序需要先執行A的_ _ init_ _ (),執行到_ _ private時, 是A的_ _private();到public()方法時候,B里面重寫了,因此調用的是B的public()方法;
當 執行到print a.__private( )時候,會出現找不到屬性錯誤,自己本身調用私有方法也會出錯,因為私有變量軋壓機制,_ _private
方法變成_A _ _ private()
,所以就找不到這個方法.
通過執行dir( )方法時候,可以查看到實例b所具有的屬性,可以發現多出了`'_A_ _private'`,`'_B__private'`
私有變量/方法的用途
私有變量/方法在自身類中不能直接調用,這樣的變量用途在哪呢?以下給出一個用途:制作端口,控制變量引用.
class A(object):
def __init__(self):
self.__private()
self.public()
def __private(self):
print 'A.__private()'
def public(self):
print 'A.public()'
def get_pri(self): # 獲取私有方法
return self.__private()
a= A( )
a.get_pri()
#---->
A.__private()
以上例子給出一個用途,在類中獲取或設置私有變量,做成端口函數,進行調用,從而引用或修改私有變量.
知識點延伸
在理解私有變量 時候,其實還需要理解一下_ _init_ _( )
,__new__()
,__call__()
,這三者的執行順序; new 用於創建對象,而 init 是在創建完成之后初始化對象狀態,__call __相當於把這個類型的對象當作函數來使用,相當於重載了括號運算符(可參考這里).
總結
- 定義私有變量,只需在變量前加上兩個下划線'_';
- 類中的私有變量通過轉換,變成
_ClassName__variableName
; - 通過在類中定義接口,實現私有變量的讀取和修改;
- 類的生成
__new__()
-->__init__()
,之后可了解單例模式實現
參考資料
[1].init()注意事項
http://www.cnblogs.com/zyxstar2003/archive/2011/03/21/1989954.html
[2].理解python命名規則
http://blog.csdn.net/gzlaiyonghao/article/details/1734990
[3].python私有屬性和方法
http://www.cnpythoner.com/post/295.html
[4].python 命名規范
http://www.codesky.net/article/201202/165214.html