默认情况下,属性在Python 中都是“public”。
1:双下划线(__)
Python 为类元素(属性和方法)的私有性提供初步的形式。由双下划线开始的属性在运行时被“混淆”,所以直接访问是不允许的。实际上,会在名字前面加上下划线和类名。
class pubpri(object): def __init__(self, num): self._num= num self.__num = num self.__num__= num self.pubnum = num >>> n1 = pubpri(3) >>> n1._num 3 >>> n1.__num__ 3 >>> n1.pubnum 3 >>>n1.__num Traceback(most recent call last): File"<stdin>", line 1, in <module> AttributeError:'pubpri' object has no attribute '__num' >>>n1._pubpri__num 3
尽管这样做提供了某种层次上的私有化,但算法处于公共域中,并且很容易被破解。
这种名字混淆的另一个目的,是为了保护__XXX 变量不与父类名字空间相冲突。如果在类中有一个__XXX 属性,它将不会被其子类中的__XXX 属性覆盖。使用__XXX,子类的代码就可以安全地使用__XXX,而不必担心它会影响到父类中的__XXX。
2:单下划线(_)
在一个模块中以单下划线开头的变量和函数被默认当作内部函数,如果使用from a_module import * 导入时,这部分变量和函数不会被导入。不过值得注意的是,如果使用 import a_module 这样导入模块,仍然可以用a_module._some_var 这样的形式访问到这样的对象。比如,假设test.py内容如下:
import sys _modulenum = 3 __modulenum = 3 __modulenum__ = 3 pubnum = 3 def _fun(): print 'this is',sys._getframe().f_code.co_name def __fun(): print'this is ', sys._getframe().f_code.co_name def __fun__(): print'this is ', sys._getframe().f_code.co_name def fun(): print'this is ', sys._getframe().f_code.co_name >>> from test import * >>>_modulenum ... NameError: name'_modulenum' is not defined >>>__modulenum ... NameError: name'__modulenum' is not defined >>>__modulenum__ ... NameError: name'__modulenum__' is not defined >>>pubnum 3 >>> _fun() ... NameError: name'_fun' is not defined >>> __fun() ... NameError: name'__fun' is not defined >>>__fun__() ... NameError: name'__fun__' is not defined >>> fun() this is fun >>> import test >>>test._modulenum 3 >>>test.__modulenum 3 >>>test.__modulenum__ 3 >>>test.pubnum 3 >>>test._fun() this is _fun >>>test.__fun() this is __fun >>>test.__fun__() this is __fun__ >>>test.fun() this is fun
双下划线开头双下划线结尾的是一些 Python 的特殊对象,如类成员的 __init__、__del__、__add__、__getitem__等。 Python 官方推荐永远不要将这样的命名方式应用于自己的变量或函数,而是按照文档说明来使用。
注意,私有化都是针对外部而言,在类内部,依然可以使用正常的访问方式,在类的外部就必须进行“混淆”了。比如:
class test(object): __cversion =1.1 def __init__(self): self.__iversion = 1.2 def fun(self): print self.__iversion print test.__cversion print self._test__iversion print self._test__cversion >>> from test import test >>> t1 = test() >>> t1.fun() 1.2 1.1 1.2 1.1 >>> t1.__iversion Traceback (most recent call last): File"<stdin>", line 1, in <module> AttributeError: 'test' object has no attribute'__iversion' >>> t1._test__iversion 1.2 >>> t1.__cversion Traceback (most recent call last): File"<stdin>", line 1, in <module> AttributeError: 'test' object has no attribute'__cversion' >>> t1._test__cversion 1.1
参考:
http://www.zhihu.com/question/19754941