1
import abc

class Agenda(metaclass=abc.ABCMeta):
    def __init__(self):
        self.__items = []

    @abc.abstractclassmethod 
    def addItem(self,item):
        pass

    @abc.abstractclassmethod 
    def getItem (self):
        pass

    def isEmpty(self):
        return self.__items == []

    def clear(self):
        self.__items = []

class StackAgenda(Agenda):
    def __init__(self):
        super().__init__()

    def addItem(self,item):
        self.__items.append(item)

    def getItem(self):
        return self.__items.pop()

When i try to use any of the StackAgenda methods it tells me that StackAgenda object doesn't have the self.__items attribute. I really don't understand why this is happening, i probably made a dumb error that i cannot find. Thanks in advance!

2
  • 1. __foo names are a misfeature, and lead to your problem. Never use them. Commented Feb 14, 2014 at 18:33
  • 2
    2. You don't want to have non-exposed stuff in an ABC for the most part. It forces concrete subclasses to have a certain implementation. Commented Feb 14, 2014 at 18:34

2 Answers 2

5

You have run into name mangling - change your double underscore prefix into a single underscore and you will be able to get at _items.

Python provides psuedo-private members for you when you use __ (double underscores) by changing the name of the member into _{classname}{original_name} wherever it is referenced in the original class. You can still get at the member in subclasses by making explicit reference to the renamed field, but that is like breaking out reflection in statically typed language ... it means all other options have failed.

What you probably want to do is provide an implementation for your abstract method:

# These are methods, not class methods
@abc.abstractmethod 
def addItem(self, item):
    self.__items.append(item)

@abc.abstractmethod 
def getItem (self):
    return self.__items.pop()

Then, in your subclass you can just call super().getItem() and super().addItem(item) ... but in that case there is really no need for an ABC.

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

5 Comments

My professor has told me that all of my instance variables should be private. Won't this make it not private? I feel like i have done this before and it has worked.
There's no "private/public" access in Python. Just developers convention.
Well the reality of the situation is that i will lose points if i dont have __. Is there a way to do this or am i just going to have to do it with _? I accidentally figured out that private variables were not actually a thing in lab last week and he told me that it is just a "good habit" to use the double underscore.
You are definitely right, it works with 1, but not 2. I don't fully understand why though, none of my classmates had this problem.
@user2807779, There's a very good chance you've misunderstood your prof. Insofar as this is good practice (it's not according to most people), it DEFINITELY isn't applicable here. The point (if there was one) of double-underscore attributes is for limiting to ONE class -- it wouldn't apply to accessing it from OTHER classes.
1

__foo attributes are magical. self.__items in Agenda is magically changed to self._Agenda__items behind the scenes. self.__items in StackAgenda becomes self._StackAgenda__items behind the scenes.

  1. Best practice is to never, ever use __foo attributes.

  2. Even if we were the small minority of crazy folks who did want to use them, this is not an application for them, nor would they be an application for private attributes if Python had them (which it doesn't.)

2 Comments

I don't know that I would say never - the docs have a good example of one case where you might want to use mangled names to keep a reference to the original implementation of a method.
@SeanVieira, I don't agree that it's a good idea in that case. __foo names are a misfeature that should be avoided. The only decent application of them (self.__super in the frameworks that used it) is no longer applicable. It's unfortunate if you're trying to reference a specific superclass's implementation to start with, but if you are going to for some reason, then using MyClass._foo is 1000x better than using self._MyClass__foo/self.__foo. The linked example could be better written by putting the implementation outside of the class entirely. (Also, it defies LSP to contrive it.)

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.