Python Super() Raises Typeerror

Python super() raises TypeError

The reason is that super() only operates on new-style classes, which in the 2.x series means extending from object:

>>> class X(object):
def a(self):
print 'a'

>>> class Y(X):
def a(self):
super(Y, self).a()
print 'b'

>>> c = Y()
>>> c.a()
a
b

Python 3: super() raises TypeError unexpectedly

You're using super() without arguments in a generator expression. The super() is magic - it relies on information in the caller frame. Since the generator expression creates an additional function, super() without arguments does not work there. However since your superclass is not probable to change in the middle of execution of a method, you can move it out of the generator expression - this should also speed things up:

def to_expr(self):
bracket_complex = super().bracket_complex
return (" " + str(self.op) + " ").join(bracket_complex(child) for child in self.children)

However as static methods are "inherited" in Python, you could call the super method via self provided that you didn't override it in a subclass. Thus in this simple case you can write:

def to_expr(self):
return (" " + str(self.op) + " ").join(self.bracket_complex(child) for child in self.children)

The implementation detail is that if no arguments are provided, the first argument shall be the value that is in the __class__ cell of the caller frame, and second shall be the first argument given to the caller function. Usually you just get a SystemError when using super in a wrong place, but generator expressions are wrapped inside an implicit generator function which creates another call frame. Unfortunately this function gets an argument, which leads the super() to complain with this exception.

So normally super() would be passed Foo there as the first argument, but within generator expression, a generator object was passed - and thus it is obvious that TypeError needs to be raised.

super() raises TypeError: must be type, not classobj for new-style class

Alright, it's the usual "super() cannot be used with an old-style class".

However, the important point is that the correct test for "is this a new-style instance (i.e. object)?" is

>>> class OldStyle: pass
>>> instance = OldStyle()
>>> issubclass(instance.__class__, object)
False

and not (as in the question):

>>> isinstance(instance, object)
True

For classes, the correct "is this a new-style class" test is:

>>> issubclass(OldStyle, object)  # OldStyle is not a new-style class
False
>>> issubclass(int, object) # int is a new-style class
True

The crucial point is that with old-style classes, the class of an instance and its type are distinct. Here, OldStyle().__class__ is OldStyle, which does not inherit from object, while type(OldStyle()) is the instance type, which does inherit from object. Basically, an old-style class just creates objects of type instance (whereas a new-style class creates objects whose type is the class itself). This is probably why the instance OldStyle() is an object: its type() inherits from object (the fact that its class does not inherit from object does not count: old-style classes merely construct new objects of type instance). Partial reference: https://stackoverflow.com/a/9699961/42973.

PS: The difference between a new-style class and an old-style one can also be seen with:

>>> type(OldStyle)  # OldStyle creates objects but is not itself a type
classobj
>>> isinstance(OldStyle, type)
False
>>> type(int) # A new-style class is a type
type

(old-style classes are not types, so they cannot be the type of their instances).

super() fails with error: TypeError argument 1 must be type, not classobj when parent does not inherit from object

Your problem is that class B is not declared as a "new-style" class. Change it like so:

class B(object):

and it will work.

super() and all subclass/superclass stuff only works with new-style classes. I recommend you get in the habit of always typing that (object) on any class definition to make sure it is a new-style class.

Old-style classes (also known as "classic" classes) are always of type classobj; new-style classes are of type type. This is why you got the error message you saw:

TypeError: super() argument 1 must be type, not classobj

Try this to see for yourself:

class OldStyle:
pass

class NewStyle(object):
pass

print type(OldStyle) # prints: <type 'classobj'>

print type(NewStyle) # prints <type 'type'>

Note that in Python 3.x, all classes are new-style. You can still use the syntax from the old-style classes but you get a new-style class. So, in Python 3.x you won't have this problem.

Why does super()() not do the same as super().__init__()?

super() objects can't intercept most special method calls, because they bypass the instance and look up the method on the type directly, and they don't want to implement all the special methods when many of them won't apply for any given usage. This case gets weirder, super()() would try to lookup a __call__ method on the super type itself, and pass it the super instance.

They don't do this because it's ambiguous, and not particularly explicit. Does super()() mean invoke the super class's __init__? Its __call__? What if we're in a __new__ method, do you invoke __new__, __init__ or both? Does this mean all super uses must implicitly know which method they're called in (even more magical than knowing the class they were defined in and the self passed when constructed with zero arguments)?

Rather than deal with all this, and to avoid implementing all the special methods on super just so it can delegate them if they exist on the instance in question, they required you to explicitly specify the special method you intend to call.

python super() function error?

super() (without arguments) was introduced in python3
Here is python2 implementation.

class electricCar(car):
def __init__(self, make, model, year):
super(electricCar,self).__init__(make, model, year)

you could refer this question for general inheritance syntax issue regarding python2 and python3

Python super() argument 1 must be type, not classobj

No, you did use super correctly. The first line:

class foo():

should be

class foo(object):

The reason for this is that your class is not a "new-style" class. super() only works on new style classes



Reference: https://www.programiz.com/python-programming/methods/built-in/super



Related Topics



Leave a reply



Submit