Super() Raises "Typeerror: Must Be Type, Not Classobj" for New-Style Class

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.

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

Frame is not a new-style class, but super requires new-style classes to work. In python-3.x where everything is a new-style class the super will work properly.

You need to hardcode the superclass and method in python 2:

Frame.__init__(self, master)

Like they do in the official documentation.

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

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

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

You should do instead of super(chat_id, user1).__init__() you should do:

super().__init__(chat_id, user1) # Work in Python 3.6
super(GroupMessage, self).__init__(chat_id, user1) # Work in Python 2.7

or

Chats.__init__(self, chat_id, user1)

This last option is not recommended if exist change that your class hierarchy change in the future. I really don't like it for others motive but still worth it a mention.

python decorator on class: TypeError: super() argument 1 must be type, not function

I studied @dataclass implementation and found the correct way. Unlike what's said in docs and guides elsewhere, Class decorator implementation is slightly different than function decorator -- we don't need to receive args and call it.

Here is the one that works:

def register(cls=None, name=None):
"""
A decorator for registering modules
:param name: (optional) name for this component
"""
def _wrap_cls(cls):
registry[name or cls.__name__] = cls
return cls
if cls is None:
return _wrap_cls
else:
return _wrap_cls(cls)

Why does the super() call work in a Python class that derives from an ABC?

super() does not create an instance of the parent.

An instance of super (it's a type, not a function) provides a proxy for for some set of classes so that an attribute lookup resolves to the correct class's value. Calling super().__init__ simply starts looking in the MRO of type(self), starting at A, for an attribute named __init__.

When arguments are explicitly provided to super, the second argument determines whose MRO you will search, and the first argument determines where in the MRO you start search (namely, the next class after the argument in the MRO).

An example with an extremely unorthodox use of super:

>>> class A:
... def foo(self):
... print("A")
...
>>> class B(A):
... def foo(self):
... print("B")
...
>>> b = B()
>>> x = super(B, b)
>>> type(x)
<class 'super'>
>>> x.__thisclass__
<class '__main__.B'>
>>> x.__self__ is b
True
>>> x.foo()
A

super itself doesn't really have optional arguments, but the context in which you almost always use it strongly imply which arguments should be passed, so Python 3 was engineered to supply them for you.

Why does super closure not use the new base class given by a metaclass?

The problem here is that your dynamic class does not inherit from itself (Class) at all - the implicit __class__ variable inside your __init__ points to the "hardcoded" "Class" version - but the self received when __init__ is called is an instance of the dynamic class, which does not have Class as its superclass. Thus, the arguments filled implicitly to super(): __class__ and self will mismatch (self is not an instance of the class defined in __class__ or of a subclass of it).

The reliable way to fix this is to allow proper inheritance, and forget copying the class __dict__ attributes around: let the inheritance machinery take care of calling the methods in the appropriate order.

By simply making the dynamic class inherit from your static class and the dynamic-base, all methods are in place, and self will be a proper instance from the baked-in __class__ from __init__.__class__ still points to the static Class, but the conditions for super to be called are fulfilled - and super does the right thing, by looking for the supermethods starting from the self parameter - the newly created dynamic subclass which inherits both from your static Class and the new Base, and calls the methods on Base as they are part of the __mro__ of the new class, in the correct place.

Ok - sounds complicated - but with some print statements added we can see the thing working:


class Base:
def __init__(self):
print("at base __init__")

class Meta(type):
def __call__(cls, obj, *args, **kwargs):
dynamic_ancestor = type(obj)
bases = (cls, dynamic_ancestor,)

new_cls = type(f"{cls.__name__}__{dynamic_ancestor.__name__}", bases , {})
instance = new_cls.__new__(new_cls, *args, **kwargs)
instance.__init__(*args, **kwargs)
return instance

class Class(metaclass=Meta):
def __init__(self, *args, **kwargs):
print(__class__.__bases__)
print(self.__class__.__bases__)
print(isinstance(self, Class))
print(isinstance(Class, Meta))
print(isinstance(self, __class__))
print(isinstance(self, self.__class__))
print(self.__class__.__mro__, __class__.__mro__)
super().__init__(*args, **kwargs)

Class(Base())

Outputs:

at base __init__
(<class 'object'>,)
(<class '__main__.Class'>, <class '__main__.Base'>)
True
True
True
True
(<class '__main__.Class__Base'>, <class '__main__.Class'>, <class '__main__.Base'>, <class 'object'>) (<class '__main__.Class'>, <class 'object'>)
at base __init__


Related Topics



Leave a reply



Submit