子类方法在python中覆盖

Min*_*HEN 4 python overriding subclass

我写了一个python测试代码:

class Parent(object):
    @classmethod
    def dispatch(klass):
        print 'klass = %s' % klass
        return klass().__dispatch()
    def __dispatch(self):
        print 'This Parent.__dispatch()'
        print self


class Child(Parent):
    def __dispatch(self):
        print 'This Child.__dispatch()'
        print self


if __name__=='__main__':
    print 'Calling Parent.dispatch() ...\n'
    Parent.dispatch()
    print ''
    print 'Calling Child.dispatch() ...\n'
    Child.dispatch()
    print '\n-END'
Run Code Online (Sandbox Code Playgroud)

输出是:

 Calling Parent.dispatch() ...

 klass = <class '__main__.Parent'> 
 This Parent.__dispatch()
 <__main__.Parent object at 0x0000000002D3A2E8>

 Calling Child.dispatch() ...

 klass = <class '__main__.Child'> 
 This Parent.__dispatch()
 <__main__.Child object at 0x0000000002D3A2E8>

 -END
Run Code Online (Sandbox Code Playgroud)

奇怪的是为什么没有调用Child类的覆盖方法'__dispatch(self)'.

有人能解释一下吗?

谢谢.

Mar*_*ers 5

以双下划线开头的方法名称会自动损坏; 在内部,字符串前_ClassName置于方法名称:

>>> class Foo(object):
...     def __bar(self):
...         pass
... 
>>> Foo.__dict__.keys()
['__dict__', '__module__', '__weakref__', '__doc__', '_Foo__bar']
Run Code Online (Sandbox Code Playgroud)

对于在类中的任何其他方法中引用此方法名称的任何内容,也会执行此重命名.

因此,您的__dispatch()方法被重命名为_Parent__dispatch(),并且该dispatch()方法被更改为调用self._Parent__dispatch().同样,你的Child类有一个_Child__dispatch()方法,因此它不会覆盖_Parent__dispatch()它的超类方法.

这就是你看到你看到的结果的原因; 将您的__dispatch()方法重命名为_dispatch()(只有一个下划线),它将按预期工作.

为什么python这样做?它是一种提供私有属性和方法的形式,它们不会被从它们继承的类意外地覆盖.请参阅Python表达式引用中的私有名称mangling.

PEP 8 Python的风格指南是这样说的关于私人名字改编:

如果您的类要进行子类化,并且您具有不希望使用子类的属性,请考虑使用双前导下划线和没有尾随下划线来命名它们.这将调用Python的名称修改算法,其中类的名称被修改为属性名称.如果子类无意中包含具有相同名称的属性,这有助于避免属性名称冲突.

注1:请注意,在修改的名称中只使用简单的类名,因此如果子类同时选择相同的类名和属性名,则仍然可以获得名称冲突.

注意2:名称修改可以进行某些用途,例如调试 __getattr__(),不太方便.但是,名称修改算法已有详细记录,并且易于手动执行.

注3:不是每个人都喜欢名字错误.尽量平衡避免意外姓名冲突与高级呼叫者潜在使用的需要.