类访问私有方法的最佳方式(私有名称改编)
如果我有这个:
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()
我不确定让一个私有方法也以两个下划线结尾在 Python 中是否合适。
还有一种我认为不太优雅的方法是:
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 中从类内部访问私有方法?
1 个回答
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
你不应该给函数(和方法不同)起带有双下划线开头的名字,因为这样会在你尝试从类内部访问它们时出现问题——这个函数就变得无法访问了,因为没有类名可以加在它前面。
如果你想表示一个函数是私有的,可以用一个下划线开头,但 我们都是成年人了。