Calling super().__new__()
when overriding __new__
in a metaclass contains the following function signature:
class MyMeta(type):
def __new__(cls, name, bases, classdict):
clsobj = super().__new__(cls, name, bases, classdict)
However, when overriding __new__
in a normal class, we have the following:
class A:
def __new__(cls, *a, **kw):
clsobj = super().__new__(cls)
Passing any other arguments to super()
in A.__new__
will lead to the following error:
TypeError: object.__new__() takes exactly one argument (the type to instantiate)
I understand that in the second case, we are dealing with object.__new__
while in the first case we are dealing with type.__new__
.
My question is, why are these function signatures different? Why does object.__new__
only accept cls
?
object
and type
have an interesting relationship. object
is an instance of type
, but type
is a subclass of object
.
__new__
, however, focuses on the creation of an instance of a class, and so object.__new__
is the lowest common denominator: it does virtually nothing on its own, because there is virtually nothing that instances of every possible class have in common. As such, object.__new__
needs no more information than the type its return value will have.
type.__new__
does quite a bit more than object.__new__
: it has to create an object that itself is capable of creating new objects. This requires quite a bit more information, so type.__new__
defines several additional parameters when it overrides object.__new__
.
Note, however, that type
itself does not use super
; if you define two classes
class A:
def __new__(cls, *args, **kwargs):
print("In A.__new__")
return super().__new__(cls)
class B(type, A):
def __new__(cls, name, bases, dct, *args, **kwargs):
print("In B.__new__")
return super().__new__(cls, name, bases, dct)
you'll see that B("B", (), {})
outputs In B.__new__
but not In A.__new__
. type.__new__
is the end of the line, so to speak, for creating metaclasses.
Typically, though, you wouldn't mix classes like this. Just like you rarely include object
in the list of base classes for a class (I'm almost willing to say you never would), you don't often inherit from type
and another (meta)class, and I can't think of any reason why you would try to inherit from both type
and a non-type subclass of object
.