super confused

D

Daniel Klein

Why does 'super' require the classname as an argument?

For example, I am subclassing 'list' and overriding all of the methods
that allow a new object to be added to the list as follows...


class ValidatedList(list):

# We only need to override methods which add objects to the list.

def __new__(cls, alist = []):
for objekt in alist:
_validate(objekt)
return list.__new__(cls, alist)

def append(self, objekt):
_validate(objekt)
# list.append(self, objekt)
super(ValidatedList,self).append(objekt)

def extend(self, alist):
for objekt in alist
_validate(objekt)
list.extend(self, alist)

def insert(self, index, objekt):
_validate(objekt)
list.insert(self, index, objekt)

def _validate(objekt):
# do some validation and raise a TypeError (or whatever)
# if it does not pass the validation.


I understand the implications of diamond shaped hierarchies. But the
question remains as to why it is necessary to for the class name to be
the first argument to 'super'. Is there a scenario where you would use
a different class name?

In Smalltalk, a message send to 'super' simply means to send a message
to self but start looking in the superclass first for the method. I
realize Smalltalk is a single-inheritance language, but doesn't
explain why, in Python, you need to specify the class name as a
parameter.

As an aside, you will notice in the 'append' method, there are two
ways to do the same thing, and either way could be used in the other
methods as well. Which brings up my second question: Is one way more
correct/efficient/better/pick your adjective? I'm very inclined to use
the 'super' method cos that means I won't have to worry about changing
things in the future.


I did spend some time Googling but didn't find anything.

Thanks for your time,

Daniel Klein
 
D

Duncan Booth

In Smalltalk, a message send to 'super' simply means to send a message
to self but start looking in the superclass first for the method. I
realize Smalltalk is a single-inheritance language, but doesn't
explain why, in Python, you need to specify the class name as a
parameter.

The problem is that super needs two classes to operate. It has to know the
type of the object (which is why you pass it 'self'), but it also has to
know where to start in the inheritance hierarchy. If super was a keyword
with some magic properties, then it might be able to pick up the correct
class automatically, but its actually just a boring ordinary function, so
you have to tell it.
As an aside, you will notice in the 'append' method, there are two
ways to do the same thing, and either way could be used in the other
methods as well. Which brings up my second question: Is one way more
correct/efficient/better/pick your adjective? I'm very inclined to use
the 'super' method cos that means I won't have to worry about changing
things in the future.
Actually these do slightly different things:
class ValidatedList(list):
...
def append(self, objekt):
_validate(objekt)
# list.append(self, objekt)
super(ValidatedList,self).append(objekt)

If you were to subclass ValidatedList, and the subclass also inherits from
another subclass of list, then the call through super might not call
list.append directly.

class List2(list):
def append(self, objekt):
return super(List2, self).append(objekt)

class Painful(ValidatedList, List2):
pass

ouch = Painful()
ouch.append('oops')

Calling ouch.append invokes ValidatedList.append which passes the call up
to List2.append, which then calls list.append. If ValidatedList.append
called list.append directly then a call to ouch.append would never pass
through List2.append.

So when to use super, and when to call the base class directly? If you
don't expect diamond inheritance hierarchies, and you aren't writing a
general purpose library for other people, then I would probably want to
invoke the base class directly. It's faster (if you care), but also clearer
to read. If those conditions don't hold, then use super.

Either way use plenty of unit tests so that if at some time your
assumptions no longer apply you'll find out about it quickly.
 
G

Greg Chapman

In Smalltalk, a message send to 'super' simply means to send a message
to self but start looking in the superclass first for the method. I
realize Smalltalk is a single-inheritance language, but doesn't
explain why, in Python, you need to specify the class name as a
parameter.

You can get something like this using the autosuper trick from
Lib/test/test_descr.py. You end up sending messages to self.__super, but at
least it avoids repeatedly typing long class names in the method
implementations. If you don't like using metaclasses, you could create a
function to add the __super attribute after the class has been declared:

def class_mangle_name(klassname, attrname):
klassname = re.sub('^_+', '', klassname)
if klassname:
return '_'+klassname+attrname
return attrname


def addsuper(cls):
setattr(cls, class_mangle_name(cls.__name__, '__super'), super(cls))

class ValidatedList(list):
def append(self, objekt):
_validate(objekt)
self.__super.append(objekt)
...

addsuper(ValidatedList)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top