您的位置:首页 > 编程语言 > Python开发

Python变量-下划线,私有变量

2014-10-16 10:46 309 查看

Python 用下划线作为变量前缀和后缀指定特殊变量。

_xxx 不能用'from module import *'导入

__xxx__ 系统定义名字

__xxx 类中的私有变量名

以单下划线开头(_foo)的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用“from xxx import *”而导入;

以双下划线开头的(__foo)代表类的私有成员;

以双下划线开头和结尾的(__foo__)代表python里特殊方法专用的标识,如 __init__()代表类的构造函数。

当变量名出现在代码块中,那它就是本地变量;

当变量名出现在模块中,它就是全局变量。

代码块就是可作为可执行单元的一段Python程序文本;模块、函数体和类定义都是代码块。不仅如此,每一个交互脚本命令也是一个代码块;一个脚本文件也是一个代码块;一个命令行脚本也是一个代码块。

"单下划线" 开始的成员变量叫做保护变量,意思是只有类对象和子类对象自己能访问到这些变量;

"双下划线" 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。

*****************************************************

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()'

b = B()

初探

正确的答案是:

A.__private() //只有类对象自己能访问,

B.public()

我们可以把代码分为三个代码块:类A的定义、类B的定义和变量b的定义。

根据类定义,我们知道代码给类A定义了三个成员变量(Python的函数也是对象,所以成员方法称为成员变量也行得通。);类B定义了两个成员变量。这可以通过以下代码验证:

>>> dir(A)

['_A__private', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'public']

>>> dir(B)

['_A__private', '_B__private', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'public']

>>> b.__private()

Traceback (most recent call last):

File "<pyshell#278>", line 1, in <module>

b.__private()

AttributeError: 'B' object has no attribute '__private'

>>>

也就是说私有变量__foo经过mangle成为_ClassName__foo后继承给了子类。

转换机制是这样的:在变量前端插入类名,再在前端加入一个下划线字符。这就是所谓的私有变量轧压(Private name mangling)。如类A里的__private标识符将被转换为_A__private,这就是上一节出现_A__private和__private消失的原因了。

因为类A定义了一个私有成员函数(变量),所以在代码生成之前先执行私有变量轧压(注意到上一节标红的那行字没有?)。轧压之后,类A的代码就变成这样了:

class A(object):

def __init__(self):

self._A__private()
# 这行变了

self.public()

def _A__private(self):
# 这行也变了

print 'A.__private()'

def public(self):

print 'A.public()'

因为在类B定义的时候没有覆盖__init__方法,所以调用的仍然是A.__init__,即执行了self._A__private(),自然输出“A.__private()”了。

==============================================================

下面的两段代码可以增加说服力,增进理解:

>>> class C(A):

def __init__(self):
# 重写__init__,不再调用self._A__private

self.__private()
# 这里绑定的是_C_private

self.public()

def __private(self):

print 'C.__private()'

def public(self):

print 'C.public()'

>>> c = C()

C.__private()

C.public()

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/gudesheng/archive/2008/03/11/2169038.aspx


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: