views:

216

answers:

3

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.

+3  A: 

The 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.

Ignacio Vazquez-Abrams
+6  A: 

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.

AndiDog
Upvoted for including python disassembly to explain the language. :)
Daniel Goldberg
Thanks! that solved it too :)
wrongusername
+1  A: 
  • 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.

Mike Graham