I have a private method def __pickSide(self):
in a parent class that I would like to override in the child class. However, the child class still calls the inherited def __pickSide(self):
. How can I override the function? The child class's function name is exactly the same as the parent's function name.
views:
216answers:
3The problem you're seeing is that the double underscores mangle the function name even in calls. This prevents polymorphism from working properly since the name it is mangled to is based on the name of the class the method is defined in, and not the name of the class of the object that is being referenced. Replacing the double underscores with something else will solve this.
Let's look at the easiest example:
from dis import dis
class A(object):
def __pick(self):
print "1"
def doitinA(self):
self.__pick()
class B(A):
def __pick(self):
print "2"
def doitinB(self):
self.__pick()
b = B()
b.doitinA() # prints 1
b.doitinB() # prints 2
dis(A.doitinA)
print
dis(B.doitinB)
The disassembly is as follows:
8 0 LOAD_FAST 0 (self)
3 LOAD_ATTR 0 (_A__pick)
6 CALL_FUNCTION 0
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
15 0 LOAD_FAST 0 (self)
3 LOAD_ATTR 0 (_B__pick)
6 CALL_FUNCTION 0
9 POP_TOP
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
As you can see, Python mangles function names that begin with two underscores (and accesses to such names!!) to a name that includes the class name - in this case _A__pick
and _B__pick
). That means that the class in which a function is defined determines which of the __pick
methods is called.
The solution is simple, avoid pseudo-private methods by removing the double underscores. For example, use _pick
instead of __pick
.
Using
__foo
names mangles the name of the method to make it more hassle to access it when you need to. I would recommend never using them, which makes things like testing go more smoothly.There is no private in Python, and if there was, it would prevent you from doing this anyhow. (This is the point of private stuff in languages that have it.)
The common convention to indicate that an attribute is not part of the public interface of a class it to use a single leading underscore, like
_foo
. This is sufficient for making your code clear separating your internal details from your public API.