Question

I have my pseudo Interface, which I implement several times. Each implementation is supposed to store a variable that basically defines a path to a file (a template). Because these classes are produced by a factory, I don't know which subclass is going to come up, therefore, I want to make it possible to access a class variable via an instance method.

This does not really pose a problem, however, when I inherit from my Interface, I don't want to implement the getHidden() method (in the following) several times. But calling it, the way it is written down there, will always yield hidden.

class MySuperInterface(object):
    # class Variable
    __much = "hidden"

    # instance method
    def getHidden(self):
        print self.__class__.__much

class MySub(MySuperInterface):
    __much = "this is different per subclass!"

    def soTroublesome(self):
        print self.__class__.__much

Execution

>>> sub = MySub() # I don't know this class!

>>> sub.getHidden()
hidden

>>> sub.soTroublesome()
this is different per subclass!

So, how can I implement getHidden() to access the instance's class' classvariable. I know, that the information is available, as I checked with dir(), but I have no idea how to access it. Again, I don't want to end up with a class/static method, because I don't know the class that gets out of my factory!

Thanks!

Was it helpful?

Solution

Just don't use the "__" in the class variable name and you are set.

Some Python write ups and "documentation" say that the "__" prefix is the Python way to get "private" members in a class. They are wrong.

The "__" prefix does exactly what is happening to you: ensure that the variable accessed in a method inside a class access the variable defined in that exact class (and not any of the classes that inherit from it).

The way it works is simple: at compile time, the names prefixed with "__" are "mangled", i.e. changed like this: __much -> _classname__much:

>>> class Hidden(object):
...   __hidden = False
... 
>>> dir(Hidden)
['_Hidden__hidden', '__class__',  ...]

Therefore your getHidden method will always look for the __much variable thathas had its name actually changed to _MySuperInterface__much, while the variable you want has had its name changed to _MySub__much.

If you as much as use a single underscore "_" to mean by convention the variable should not be used outside of the class, your code would work as you expect.

OTHER TIPS

You should definitely learn and try how python member access works. Use interactive Python shell (python in the command line), import your modules and experiment.

print self.__class__.__much

You don't typically need to access class members via __class__ when reading. Access them as normal members instead:

print self.__much

Python supports private members by name mangling, changing __much member of MySuperInterface class to _MySuperInterface__much. This is to avoid accessing the private member from child classes which is exactly what you are trying to do.

When you, for any reason, need to access it, you can simply use the mangled name:

print self._MySuperInterface__much
print self._MySub__much

You should typically avoid it and rethink your code instead. The easiest way to do that is to use a single underscore that still denotes internal implementation member but doesn't trigger the name mangling.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top