TypeError: super() argument 1 must be type, not classobj (Python)
Archive - Originally posted on "The Horse's Mouth" - 2009-09-18 22:18:20 - Graham EllisIf you've got an error message like this, you've called up a method from the base class of your object using "new style classes", but the base class is an "old style class". The full error message looks something like this:
Traceback (most recent call last):
File "cl_n.py", line 24, in <module>
testgroup = [train("First Great Western cl 150",80,2)]
File "cl_n.py", line 10, in __init__
super(train,self).__init__(about)
TypeError: super() argument 1 must be type, not classobj
Here's the full failing source code of my example:
class pubtrans:
def __init__(self,about):
self.info = about
def getabout(self):
return self.info
def getvehicles(self):
return 1
class train(pubtrans):
def __init__(self,about,vehicle_capacity,coaches):
super(train,self).__init__(about)
self.vc = vehicle_capacity
self.nc = coaches
def getcapacity(self):
return self.vc * self.nc
def getvehicles(self):
return self.nc
class bus(pubtrans):
def __init__(self,about,vehicle_capacity):
super(bus,self).__init__(about)
self.vc = vehicle_capacity
def getcapacity(self):
return self.vc
if __name__ == "__main__":
testgroup = [train("First Great Western cl 150",80,2)]
testgroup.append(bus("First Avon and Somerset",81))
testgroup.append(bus("Faresaver",29))
testgroup.append(train("South West Trains cl 159",75,3))
format = "%-30s %4d %d"
tpc = 0
tvc = 0
for option in testgroup:
text = option.getabout()
pass_count = option.getcapacity()
veh_count = option.getvehicles()
tpc += pass_count
tvc += veh_count
print format % (text, pass_count, veh_count)
print format % (" --- TOTAL ---",tpc,tvc)
The problem is that the base class is an old style class because it's defined without any inheritance, whereas the extended classes / derived classes / subclasses are using the new style super call. There are two ways of solving the problem.
The first (and infinitely preferable) is to switch to new style classes by having the base class inherit from object - it's as easy as changing:
class pubtrans:
to
class pubtrans(object):
The second option (not recommended, as it retains old style classes which are not supported in Python 3) is to call up the constructor of the base class directly rather than using the super call. In other words, in my example the two lines:
super(train,self).__init__(about)
super(bus,self).__init__(about)
would both become:
pubtrans.__init__(self,about)
The complete source code of the new style example is here and of the old style example is here.
P.S. It runs, when corrected, like this:
Dorothy-2:2 grahamellis$ python cl_o.py
First Great Western cl 150 160 2
First Avon and Somerset 81 1
Faresaver 29 1
South West Trains cl 159 225 3
--- TOTAL --- 495 7
Dorothy-2:2 grahamellis$