Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python method name with double-underscore is overridden?

Tags:

python

Take a look at this. Note that class B overrides A's a() method.

In [1]: class A(object):    ...:     def __init__(self):    ...:         self.a()    ...:     def a(self):    ...:         print "A.a()"    ...:             ...:           In [2]: class B(A):    ...:     def __init__(self):    ...:         super(B, self).__init__()    ...:     def a(self):    ...:         print "B.a()"    ...:             ...:           In [3]: b = B() B.a() 

No surprises there.

Now, take a look at this. Note that the method now being overridden is __a().

In [7]: class A(object):    ...:     def __init__(self):    ...:         self.__a()    ...:     def __a(self):    ...:         print "A.__a()"    ...:             ...:           In [8]: class B(A):    ...:     def __init__(self):    ...:         super(B, self).__init__()    ...:     def __a(self):    ...:         print "B.__a()"    ...:             ...:           In [9]: b = B() A.__a() 

This behaviour surprised me.

Can anyone explain why A.__a() is called instead of B.__a()?

Anything __special__ about __a?

Update: After reading Sean's answer I wanted to see if I could override the name mangled method and got this result:

In [11]: class B(A):    ....:     def __init__(self):    ....:         super(B, self).__init__()    ....:     def _A__a(self):    ....:         print "B._A__a()"    ....:             ....:           In [12]: b = B() B._A__a() 
like image 222
Jason A Avatar asked Jun 22 '11 18:06

Jason A


People also ask

What does _ and __ mean in Python?

The use of double underscore ( __ ) in front of a name (specifically a method name) is not a convention; it has a specific meaning to the interpreter. Python mangles these names and it is used to avoid name clashes with names defined by subclasses.

What are Python methods with double underscore?

A double underscore prefix causes the Python interpreter to rewrite the attribute name in order to avoid naming conflicts in subclasses. This is also called name mangling—the interpreter changes the name of the variable in a way that makes it harder to create collisions when the class is extended later.

Why do we use __ in Python?

The Python interpreter modifies the variable name with ___. So Multiple times It uses as a Private member because another class can not access that variable directly. The main purpose for __ is to use variable /method in class only If you want to use it outside of the class you can make it public.

What is overridden method in Python?

Method overriding is an ability of any object-oriented programming language that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its super-classes or parent classes.


1 Answers

keywords with a pattern of __* are class private names.

http://docs.python.org/reference/lexical_analysis.html#reserved-classes-of-identifiers

Quoting:

Names in this category, when used within the context of a class definition, are re-written to use a mangled form to help avoid name clashes between “private” attributes of base and derived classes

Private name mangling (emphasis added):

Private name mangling: When an identifier that textually occurs in a class definition begins with two or more underscore characters and does not end in two or more underscores, it is considered a private name of that class. Private names are transformed to a longer form before code is generated for them. The transformation inserts the class name in front of the name, with leading underscores removed, and a single underscore inserted in front of the class name. For example, the identifier __spam occurring in a class named Ham will be transformed to _Ham__spam. This transformation is independent of the syntactical context in which the identifier is used. If the transformed name is extremely long (longer than 255 characters), implementation defined truncation may happen. If the class name consists only of underscores, no transformation is done.

http://docs.python.org/reference/expressions.html#atom-identifiers

This means that behind the scenes, B.__a() is transformed to something like B._B__a()

like image 134
Sean Avatar answered Oct 10 '22 19:10

Sean