在Python中覆盖“私有”方法

时间:2013-02-15 15:43:16

标签: python oop methods subclass private-members

考虑使用“私有”方法的类,例如:

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>

覆盖这种方法的方法是什么?

3 个答案:

答案 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')

documented

  

__spam形式的任何标识符(至少两个前导下划线,最多一个尾随下划线)在文本上替换为_classname__spam,其中classname是具有前导下划线的当前类名(s)剥离。

但原始类的设计者认为你不应该做这样的事情,因为难以用子类化覆盖是双重下划线的全部要点:

  

名称修改有助于让子类覆盖方法而不破坏类内方法调用。