Overwriting a subclass in python

I am writing python test code 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 result:

  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 is very strange why the rewriting method "__dispatch (self)" of the Child class was not called.

Can anyone explain about this?

Thanks.

+4
source share
2 answers

Method names beginning with double underscores are automatically distorted; internally, the _ClassName string _ClassName appended to the method name:

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

This renaming is also done for anything that references 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 changed to call self._Parent__dispatch() . Similarly, your Child class has the _Child__dispatch() method, and therefore it does not override the _Parent__dispatch() method of this superclass.

That is why you see the results that you see; rename the __dispatch() methods to _dispatch() (only one underscore) and it will work as expected.

Why does python do this? This is a form of providing private attributes and methods that cannot be accidentally overridden by classes that inherit from them. See the personal name mangling in the expression reference for Python.

The Python style guide for PEP 8 talks about managing a private name:

If your class is intended to be a subclass and you have attributes that you do not want to use subclasses, consider their double leading underscores and the absence of underscores. This calls the Python Name Rename Algorithm, where the class name is mutilated into the attribute name. This helps to avoid a collision attribute name should subclasses inadvertently contain attributes with the same name.

Note 1: Note that only the simple name of the class name is used in the distorted one, therefore, if a subclass selects the same class name and attribute name, you can still get name clashes.

Note 2: Changing the name may make certain uses, such as debugging and __getattr__() , less convenient. However, the name determination algorithm is well-documented and easy to execute manually.

Note 3: Not everyone likes name manipulation. Try to balance the need to avoid accidental name conflicts with the potential use of advanced subscribers.

+5
source

Have you tried using _dispatch methods instead of __dispatch?

The fact is that __dispatch is internally translated into _NameOfTheClass_dispatch (or something like that to give a kind of behavior to the member function 'private'). It is for this reason that your redefinition fails.

If you use _dispatch, the name of the member function does not affect the underscore, and the program behaves as you wish.

0
source

Source: https://habr.com/ru/post/1434369/


All Articles