在Python中雖然有Private variable,但是不像一般程式語言一樣具有強制的效力,如果外界執意要使用還是可以呼叫的到。在這篇StackOverflow有很清楚的解釋其中的差別。
-
Module private 是指是以一個下底線 _ 開頭的變數,例如 _number 或 _getNumber()
-
Class Private 基本上是以二個下底線 __ 開頭,而且不超過一個下底線 _ 結尾的的變數名稱,例如 __number 或 __getNumber(),但是init 就不是 class private,但這種兩個下底線開頭和結尾叫 Magic methods有其特別的用途,但這個不在本文討論範圍。
Module Private
# moduleA.py
def _foo():
return 'hi'
from moduleA import *
print _foo()
以此例子來說,我們在 moduleA.py裡面定義了一個 Module private _foo(),因為Python有個規定是在Import的時侯會略過所有以underscore開頭的成員,所以_foo()會被忽略,在執行 print _foo() 的時侯就會發生 Exception:
Traceback (most recent call last):
File "D:\priavte\__init__.py", line 4, in <module>
NameError: name '_foo' is not defined
但是如果執意要用還是可以透過Import __foo,得到想要的結果
from moduleA import _foo
print _foo()
Class Private
class Foo():
__aoo = 123
def __boo(self):
return 123
def coo(self):
return 456
f = Foo()
print dir(f)
print f._Foo__boo()
print f.__boo()
可以觀察一下這三個 print 執行的結果,會發現 dir(f)是輸出:
> ['_Foo__aoo', '_Foo__boo', '__doc__', '__module__', 'coo']
_boo被加上_Foo_的Prefix,這種行為稱做 Name Mangling,多加上Class Name在前面。所以透過 f.__boo()就沒辦法直接呼叫,但是透過加上Class Name的Prefix就可以了,例如 print f._Foo__boo()
總結
Module private : _number
- 達到 Private 的效果:Import 除非明確把 name 打出來,不然 from A import * 時會自動略過所有以一個下底線 _ 開頭的變數
- 使用時機:在 Module level 下,告知外界,這些變數/函式是Private性質的,不建議外界直接存取
- 強制使用方式: 直接Import即可,例如: from A import _Number
Class Private : __number
- 達到 Private 的效果:Class 物件被建立的時侯,所有 __XXX 會被 name mangling成 __ClassName__XXX
- 使用時機:跟 Module private 一樣,就是表現出這些成員是內部使用的,不建議外界直接存取
- 強制使用方式: 使用的時侯,加上 Class name 的的 prefix
- 繼承的時侯,這些被 name mangled 的成員也會被繼承,但是是使用Parent的ClassName的Prefix,要注意一下。 在Python的世界中,Private Variable沒辦法強制讓外界無法使用,透過Naming可以讓別人知道這些Private Variable不應該直接被存取,避免誤用的Bug發生。但是如果執意要呼叫,都還是有方法的。