1

I've got a class that inherits from an abstract class in Python

class MyAbstractClass():
    __Var1 = 0

    def __init__(self):
        pass

class MySubClass(MyAbstractClass):
    def __init__(self):
        MyAbstractClass.__init__(self)

    def MyFunc(self):
        print self.__Var1

This comes out with the following error:

AttributeError: MySubClass instance has no attribute '_MySubClass__Var1'

It's good to note that these two classes are in seperate files.

I've searched around, and most suggestions were to change my code from the use of "super()" to explicit names of the parent. However, I am still reciving this error.

Any idea whats up?

1
  • You haven't said what it is you're trying to accomplish. What is the purpose of __Var1? Commented Feb 26, 2013 at 22:10

3 Answers 3

4

What you see is the name mangling. Names starting with double underscore are treated in a special way to avoid name collision in subclasses.

Basically whenever you have an __some_name attribute in a class, it is renamed automatically to _YourClass__some_name to avoid name collision when inheriting.

You can check this using the dir() function:

>>> class MyClass(object):
...     __var = 1
... 
>>> dir(MyClass)
['_MyClass__var', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

Note how the list does not contain __var but instead contains _MyClass__var.

The fix is simple: do not use variable names that start with double underscore. If you want to mark a variable as private the convention is to use a single underscore.

I want to stress again that the main purpose of the name mangling is to avoid namespace collisions with subclasses:

>>> class MyClass(object):
...     def __init__(self, val):
...             self._value = val
... 
>>> class MySubclass(object):
...     def __init__(self, val):
...             super(MyClass, self).__init__(val)
...             self._value = val ** 2  #this hides the base class attribute!
... 

Note that if the base class is from a third party library, then you can't know which private attributes are defined, since they are not part of the API. Checking with dir gives you only a hint on which name are used, but since they are an implementation detail they can change without notice.

You shouldn't use this to "mark" the attributes as private. The python convention is that attributes starting with a single underscore are private.

On a related topic, also names of the form __something__ with double underscore both at the beginning and the end of the name are treated specially. Some of them implement the special methods and thus you should never use this kind of identifier.

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

2 Comments

Oops. For whatever reason, my brain said "2 underscores" when I read the python page. It works now, thank you. What is the proper syntax for public variables?
@MintyAnt There is no syntax for public variables. Python does not distinguis between public and private, everything is public. public names are conventionally names that do not start with an underscore. In your example you could use Var1, although I'd suggest to use lowercase_with_underscore instead of CamelCase for variable/method names.
2

The double-underscore intentionally obfuscate the variable name to make it semi-private. See http://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references for more details.

To resolve the issue, change __Var1 to _Var1.

Comments

1

The double underscore in front of Var1 does name mangling. At runtime __Var1 looks like _MySubClass__Var1.

Try renaming it _Var1 , with a single underscore.

Name mangling is how Python creates private variables of a sort. It's really to prevent namespace collisions.

There is some detail on this here

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.