考虑使用“私有”方法的类,例如:
class Foo(object):
def __init__(self):
self.__method()
def __method(self):
print('42')
当我尝试继承Foo
并覆盖方法__method
时,可以看到Foo.__method
仍然被调用,而不是MoreFoo.__method
。
class MoreFoo(Foo):
def __method(self):
print('41')
>>> MoreFoo()
42
<__main__.MoreFoo object at 0x7fb726197d90>
覆盖这种方法的方法是什么?
答案 0 :(得分:18)
使用双下划线名称约定的 point 是为了防止子类(意外地)覆盖该方法。
如果你有来覆盖它,那么有人会犯一个严重的类设计错误。您可以通过命名对象来实现它:
def _Foo__method(self):
其中您为方法名称添加一个下划线和定义的类名(在这种情况下,前缀为_Foo
)。使用双下划线重命名方法和属性的过程称为private name mangling。
如果要定义一个在子类中仍然可以覆盖的“私有”方法,通常会使用一个下划线(def _method(self):
)来粘贴名称。
由于它的动态特性,Python中几乎没有任何东西是真正私有的;有点内省几乎可以达到任何目的。
答案 1 :(得分:9)
双下划线前缀调用名称修改,不等效于私有方法。它专门设计用于避免被子类覆盖(在这种情况下,方法名称变为_Foo__method
)。
如果您有一个实现细节,请在其前面加上一个下划线,这是Python方法的普遍接受标志,不能在外部使用。没有强制执行此操作,因为这不是Python的功能。
答案 2 :(得分:3)
我相信你会这样做:
class MoreFoo(Foo):
def _Foo__method(self):
print('41')
__spam
形式的任何标识符(至少两个前导下划线,最多一个尾随下划线)在文本上替换为_classname__spam
,其中classname
是具有前导下划线的当前类名(s)剥离。
但原始类的设计者认为你不应该做这样的事情,因为难以用子类化覆盖是双重下划线的全部要点:
名称修改有助于让子类覆盖方法而不破坏类内方法调用。