2

I am wrapping up a python class deque to queue to make my code more readable:

from collections import deque

class Queue(deque):
    def enqueue(self,a):
        super(Queue, self).append(a)

    def dequeue(self,a):
        super(Queue, self).popleft(a)

My question is which one I should use here, self.append() or super(Queue, self).append(), Why?

martineau
  • 119,623
  • 25
  • 170
  • 301
Bob Fang
  • 6,963
  • 10
  • 39
  • 72

4 Answers4

2

super() is used to call a base class method that is redefined in the derived class. If your class were defining append() and popleft() methods extending their behavior, it would be reasonable to use super() inside append() and popleft(). However, your example redefines nothing from deque, so there is no need for super().

The following example shows when super() is used:

class Queue(deque):
    def append(self, a):
        # Now you explicitly call a method from base class
        # Otherwise you will make a recursive call
        super(Queue, self).append(a)
        print "Append!!!"

However, in case of multiple inheritance what super() does is more complicated than just allowing to call a method from base class. Detailed understanding requires understanding MRO (method resolution order). As a result, even in the example above it is usually better to write:

class Queue(deque):
    def append(self, a):
        # Now you explicitly call a method from base class
        # Otherwise you will make a recursive call
        deque.append(self, a)
        print "Append!!!"
Ellioh
  • 5,162
  • 2
  • 20
  • 33
1

Given these two choices, you should use self.append, because your code using super is not valid Python.

The correct alternate version would be super(Queue, self).append.

Borealid
  • 95,191
  • 9
  • 106
  • 122
1

Go for self (putting aside that your use of super is incorrect as Borealid stated).

However, I believe that in this case it's better to not extend deque, but rather wrap it.

from collections import deque

class Queue(object):
    def __init__(self):
        self.q = deque

    def enqueue(self, a):
        return self.q.append(a)

    def dequeue(self, a):
        return self.q.popleft(a)

Also, note the returns - in your code they are missing and you cannot get the dequeued value.

Emil Ivanov
  • 37,300
  • 12
  • 75
  • 90
  • It's usually better to use composition (my example), rather than inheritance (your example). It's much more simple. Also, in your case the details (read: methods) or deque will leak to your class and the abstraction won't be as nice. – Emil Ivanov Jan 12 '13 at 15:09
  • 1
    Generally saying composition is better than inheritance? – Bob Fang Jan 12 '13 at 15:11
  • @dorafmon: most of the time, yes. – Emil Ivanov Jan 12 '13 at 15:12
  • May I ask why is this? Sorry I am a beginner and not very good at OOP – Bob Fang Jan 12 '13 at 15:15
  • This would take a book to explain :). Luckily, there's one verrrrrry goooood: [Code Complete](http://www.amazon.com/dp/0735619670/?tag=stackoverfl08-20). Also, look at [this](http://stackoverflow.com/questions/49002/prefer-composition-over-inheritance) question. – Emil Ivanov Jan 12 '13 at 15:17
  • Thanks a lot for your kindness and patience. – Bob Fang Jan 12 '13 at 15:19
  • @dorafmon: Whether to subclass a type or not isn't always clear-cut. This is illustrated by the classic [circle-ellipse problem](http://en.wikipedia.org/wiki/Circle-ellipse_problem) encountered when using object-oriented programming. – martineau Jan 12 '13 at 16:40
  • Composition is better if your class is just trying to reuse another class' functionality. If a base class really is a more general case of the derived one, inheritance is perfectly valid. – Ellioh Jan 12 '13 at 19:47
0

Who told you it was a good idea to even think of using super instead of self? You want to affect a single instance of the Queue, not append a to the module scope (never mind the fact that super.append throws AttributeError)

from collections import deque

class Queue(deque):
    def enqueue(self, a):
        self.append(a)

    def dequeue(self, a):
        self.popleft(a)
Amelia
  • 2,967
  • 2
  • 24
  • 39