1

Suppose I have a base class, where there's a __flag attribute accessible by a @classmethod.

class Base(object):
    __flag = None

    def __init__(self) :
        pass

    @classmethod
    def flag(self):
        return self.__flag

Suppose I also have a derived class where I change the attribute.

class Derived(Base):
    __flag = True

Then, when I try to access the attribute of the derived class, I get the attribute of the base class:

In [3]: print Derived.flag()
None

Why? I really can not understand.

0

3 Answers 3

4

This is because the "hidden" variables in Python get stored differently. There's a tiny bit of magic there.

Here's an example of why it does not work:

class Base(object):
    __flag = 'base'
    _other_flag = 'base'

    def __init__(self) :
        pass

    @classmethod
    def flag(self):
        return self.__flag

    @classmethod
    def other_flag(self):
        return self._other_flag

class Derived(Base):
    __flag = 'derived'
    _other_flag = 'derived'

print 'base flag', Base.flag()
print 'derived flag', Derived.flag()
print 'base other flag', Base.other_flag()
print 'derived other flag', Derived.other_flag()

# Note the following 2 statements:
print 'base flag property', Derived._Base__flag
print 'derived flag property', Derived._Derived__flag

print 'base other flag property', Base._other_flag
print 'derived other flag property', Derived._other_flag

As you can see at the bottom, it's stored in a different variable and silently translated to that within the Base.flag method.

Sign up to request clarification or add additional context in comments.

Comments

2

Remove the __ from __flag and it will work nicely. Like so:

class Base(object):
    flagAtt = None

    def __init__(self) :
       pass

    @classmethod
    def flag(self):
        return self.flagAtt

class Derived(Base):
    flagAtt = True

Which gives:

>>> print Derived.flag()
True
>>> print Base.flag()
None

1 Comment

Oh, it's as simple as that! Thank you very much!
1

Python performs name-mangling on variables that start with two underscores (except those that also end with two underscores), so __flag in Base is different from __flag. You can observe this by using dir:

>>> class Base(object):
...     __flag = True
... 
>>> dir(Base)
['_Base__flag', '__class__', '__delattr__', ......   # lots of others

The __flag variable is turned into _Base__flag here. In Derived it is turned into _Derived__flag, so you are not actually overriding anything, just introducing a new variable.

If you want a variable to be overridable, do not use names staring with two underscores.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.