pythonpython-3.x

Python: Cannot get attribute from superclass


I know is a pretty basic question, but I've tried for hours and still can't figure it out why I cannot access the attributes of a parent class. My code:

class Queue:
    def __init__(self):
        self.__queue_list = []

    def put(self, val):
        self.__queue_list.insert(0, val)

    def get(self):
        if len(self.__queue_list) == 0:
            raise QueueError
        else:
            val = self.__queue_list[-1]
            del self.__queue_list[-1]
            return val

class SuperQueue(Queue):
    def __init__(self):
        Queue.__init__(self)

    def isempty(self):
        li = Queue.__queue_list
        return bool(len(li))

- when running:

que = SuperQueue()
que.put(1)
que.put("dog")
que.put(False)
for i in range(4):
    if not que.isempty():
        print(que.get())
    else:
        print("Queue empty")

I get the error AttributeError: type object 'Queue' has no attribute '_SuperQueue__queue_list'

I've also tried using super()or in the child class replacing li = Queue.__queue_list with li = self.__queue_list

Nothing works


Solution

  • The issue here is that you're trying to access the __queue_list attribute directly from the Queue class, which is not allowed since it's a private attribute. Private attributes in Python are "name-mangled" to avoid naming conflicts, which is why you're getting the AttributeError

    class Queue:
        def __init__(self):
            self.__queue_list = []
    
        def put(self, val):
            self.__queue_list.insert(0, val)
    
        def get(self):
            if len(self.__queue_list) == 0:
                raise QueueError
            else:
                val = self.__queue_list[-1]
                del self.__queue_list[-1]
                return val
    
    class SuperQueue(Queue):
        def __init__(self):
            super().__init__()
    
        def isempty(self):
            return len(self._Queue__queue_list) == 0
    
    # Usage
    que = SuperQueue()
    que.put(1)
    que.put("dog")
    que.put(False)
    for i in range(4):
        if not que.isempty():
            print(que.get())
        else:
            print("Queue empty")
    

    Alternately you can use super() also:

    def isempty(self):
        return len(super().__queue_list) == 0