如果我有这个:
class Test:
def __init__(self, x):
self.x = x
def A(self):
__doA()
def __doA():
print 'A'
if __name__ == '__main__':
t = Test(1)
t.A()
显然会产生NameError: global name '_Test__doA' is not defined
根据文件:
如果在类定义中以文本方式出现的标识符以两个或多个下划线字符开头,并且不以两个或多个下划线结尾,则将其视为该类的私有名称。在为其生成代码之前,将私有名称转换为更长的形式。转换将在名称前面插入类名,删除前导下划线并插入单个下划线。例如,名为Ham的类中出现的标识符__spam将转换为_Ham__spam。此转换独立于使用标识符的语法上下文。如果转换后的名称非常长(超过255个字符),则可能会发生实现定义的截断。如果类名仅由下划线组成,则不进行转换。
我想维护这两个下划线,因为模块将被许多人使用,我想象征这些方法是私有的,但是我仍然希望类能够访问它们。
一个快速的解决方法是将方法名称更改为以两个下划线结尾,以便绕过名称修改:
class Test:
def __init__(self, x):
self.x = x
def A(self):
__doA__()
def __doA__():
print 'A'
if __name__ == '__main__':
t = Test(1)
t.A()
我不确定Pythonic是如何将私有方法以两个下划线结尾的。
另一种不太优雅的方式是IMO:
class Test:
def __init__(self, x):
self.x = x
self.__doA = globals()['__doA']
def A(self):
self.__doA()
def __doA():
print 'A'
if __name__ == '__main__':
t = Test(1)
t.A()
有没有更好的方法从python中的类内部访问私有方法?
答案 0 :(得分:1)
这是一个重新创建错误的简短脚本:
def __foo(x):
print x
__foo("foo")
class Bar(object):
def baz(self, x):
__foo(x)
Bar().baz("foo")
结果是:
foo # direct call works
Traceback (most recent call last):
File "C:/Python27/test.py", line 11, in <module>
Bar().baz("foo")
File "C:/Python27/test.py", line 8, in baz
__foo(x)
NameError: global name '_Bar__foo' is not defined # gets mangled in class, breaks
你不应该给那些带有前导双下划线的函数(与方法不同),因为当你试图从内部类中访问它们时,它会破坏名称错误 - 函数变得无法访问,因为没有类名称可以进入它的前面。
如果您想表明某个功能是私有的,请使用一个前导下划线,但we're all consenting adults here。