Reputation: 117
I write a test code of python like:
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'
And the output is:
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
It's very strange why the overwrote method '__dispatch(self)' of Child class was not called.
Does anyone can explain about this?
Thank you.
Upvotes: 5
Views: 4860
Reputation: 1125148
Methodnames that start with a double underscore are automatically mangled; internally, the string _ClassName
is prepended to the method name:
>>> class Foo(object):
... def __bar(self):
... pass
...
>>> Foo.__dict__.keys()
['__dict__', '__module__', '__weakref__', '__doc__', '_Foo__bar']
This renaming also is done for anything referencing this method name in any of the other methods in the class.
Thus, your __dispatch()
method is renamed to _Parent__dispatch()
, and the dispatch()
method is altered to call self._Parent__dispatch()
instead. Similarly, your Child
class has a _Child__dispatch()
method, and it thus does not override the _Parent__dispatch()
method of it's super-class.
This is why you see the results you see; rename your __dispatch()
methods to _dispatch()
(only one underscore) and it'll work as expected.
Why does python do this? It's a form of providing private attributes and methods, that cannot be accidentally overridden by classes that inherit from them. See private name mangling in the Python expression reference.
The PEP 8 Python Style Guide has this to say about private name mangling:
If your class is intended to be subclassed, and you have attributes that you do not want subclasses to use, consider naming them with double leading underscores and no trailing underscores. This invokes Python's name mangling algorithm, where the name of the class is mangled into the attribute name. This helps avoid attribute name collisions should subclasses inadvertently contain attributes with the same name.
Note 1: Note that only the simple class name is used in the mangled name, so if a subclass chooses both the same class name and attribute name, you can still get name collisions.
Note 2: Name mangling can make certain uses, such as debugging and
__getattr__()
, less convenient. However the name mangling algorithm is well documented and easy to perform manually.Note 3: Not everyone likes name mangling. Try to balance the need to avoid accidental name clashes with potential use by advanced callers.
Upvotes: 7
Reputation: 5544
Have you tried calling the methods _dispatch instead of __dispatch?
The point is that __dispatch is internally translated into _NameOfTheClass_dispatch (or something of the kind to give a sort of 'private' member function behavior). This is the reason why your override fails.
If you use _dispatch the name of the member function is not affected by the underscore and the program behaves as you wish.
Upvotes: 1