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
Is There Any Difference Between "Foo Is None" and "Foo == None"
Why Does Defining _Getitem_ on a Class Make It Iterable in Python
Get the Name of a Pandas Dataframe
Play an Animated Gif in Python with Tkinter
Error Installing Psycopg2, Library Not Found for -Lssl
Is There a Ceiling Equivalent of // Operator in Python
2D List Has Weird Behavor When Trying to Modify a Single Value
How to Format Date String via Multiple Formats in Python
Processing Single File from Multiple Processes
Nested for Loops Using List Comprehension
Check If a File Is Open in Python
I Expect 'True' But Get 'None'
Deep-Learning Nan Loss Reasons