Python: Hide member of base class in derived class

1.9k views Asked by At

How to override a member of base class in my derived class so that accesses to such member cause invoking the derived member? Consider folllowing example? __tmp is overwritten in B and should be return in case of a call to tmp()

class A:
    __tmp = {"A" : 1,
             "B" : 2}
    def tmp(self):
        return self.__tmp

class B(A):
    __tmp = {"A" : 10,
             "B" : 20}
    def __init__(self):
        super().__init__()

b = B()
print(b.tmp()) # Expect to print {'A': 10, 'B': 20} here
2

There are 2 answers

2
Lauritz V. Thaulow On BEST ANSWER

Don't use obfuscated variable names:

class A:
    _tmp = {"A" : 1,
             "B" : 2}
    def tmp(self):
        return self._tmp

class B(A):
    _tmp = {"A" : 10,
             "B" : 20}
    def __init__(self):
        super().__init__()

b = B()
print(b.tmp()) # Works as expected

The problem was that self.__tmp is name-mangled behind the scenes by python and resolves to self._A__tmp since tmp is a method of the A class. You wanted self._B__tmp. If you had redefined the tmp method in B it would have worked, but that's a silly way of doing it, since it defeats one of the purposes of inheritance -- avoiding code duplication.

Reserve the use of __private variables for when you wish to avoid name clashes with the attributes of subclasses. In this case, you really wish to achive such a naming collition.

If you want to make an attribute private, it suffices with a single underscore, since we're all consenting adults here.

1
Robert Caspary On

From the description it isn't clear to my, why should be wanted and should make sense. Looks like a rather strange design. But nevertheless, why don't you just overwrite the getter?

class A( object ):
    __tmp = {"A" : 1,
             "B" : 2}
    def tmp( self ):
        return self.__tmp

class B( A ):
    __tmp = {"A" : 10,
             "B" : 20}
    def __init__( self ):
        super( B, self ).__init__()

    def tmp( self ):
        return B.__tmp


b = B()
print( b.tmp() )  # Expect to print {'A': 10, 'B': 20} here