Search code examples
pythonattributeerror

Python property inheritance


I am new to python and I wasn't sure what I was doing was correct. I have a base class A and an inherited class B.

class A(object):

    def __init__(self, name):
        self.__name = name

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, name):
        self.__name = name

class B(A):
    def __init__(self, name):
        super(NominalValue, self).__init__(name)

    @property
    def name2(self):
        return self.__name2

    @name2.setter
    def name2(self, n):
        self.__name2 = n

    def toString():
        print self.__name + self.__name2

if __name__ == "__main__":
    instance = B('name');
    instance.toString()

When I run this it complains that class B does not have any attribute __name.

AttributeError: 'B' object has no attribute '_B__name'

I am clearly not doing the inheritance correctly. How do you treat properties to be correctly inherited and avoid repeating attributes in the inherited class?


Solution

  • Attributes that begin with two underscores like your __name are signified as being private variables. There's no actual PROTECTION done to these (that is to say: if you can find it, you can access it), but they are name-mangled to be less easy to access. More information about that can be found on the docs page

    Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped.

    Because of this, even though you're inheriting A's __name attribute, you don't have an attribute __name in any object of type B. What you have is a _A__name attribute. That's how the name-mangling works: __attributename becomes _classname__attributename

    You could use _name instead, which is just a flag to future users that this isn't supposed to be public. Then your whole code should work.