Calls to constructors require special handling within type checkers.
At runtime, a call to a class' constructor typically results in the invocation of three methods in the following order:
- The
__call__method of the metaclass (which is typically supplied by thetypeclass but can be overridden by a custom metaclass and which is responsible for calling the next two methods) - The
__new__static method of the class - The
__init__instance method of the class
Type checkers should mirror this runtime behavior when analyzing a constructor call.
When evaluating a constructor call, a type checker should first check if the
class has a custom metaclass (a subclass of type) that defines a __call__
method. If so, it should evaluate the call of this method using the supplied
arguments. If the metaclass is type, this step can be skipped.
If the evaluated return type of the __call__ method indicates something
other than an instance of the class being constructed, a type checker should
assume that the metaclass __call__ method is overriding type.__call__
in some special manner, and it should not attempt to evaluate the __new__
or __init__ methods on the class. For example, some metaclass __call__
methods are annotated to return NoReturn to indicate that constructor
calls are not supported for that class.
class Meta(type):
def __call__(cls, *args, **kwargs) -> NoReturn:
raise TypeError("Cannot instantiate class")
class MyClass(metaclass=Meta):
def __new__(cls, *args, **kwargs) -> Self:
return super().__new__(cls, *args, **kwargs)
assert_type(MyClass(), Never)
If no return type annotation is provided for __call__, a type checker may
assume that it does not override type.__call__ in a special manner and
proceed as though the return type is an instance of the type specified by
the cls parameter.
After the metaclass __call__ method has been evaluated, a type checker
should evaluate the __new__ method of the class (if applicable) using
the supplied arguments. This step should be skipped if the class does not
define a __new__ method and does not inherit a __new__ method from
a base class other than object.
If the class is generic and explicitly specialized, the type checker should
partially specialize the __new__ method using the supplied type arguments.
If the class is not explicitly specialized, class-scoped type variables should
be solved using the supplied arguments passed to the constructor call.
class MyClass[T]:
def __new__(cls, x: T) -> Self:
return super().__new__(cls)
# Constructor calls for specialized classes
assert_type(MyClass[int](1), MyClass[int])
assert_type(MyClass[float](1), MyClass[float])
MyClass[int](1.0) # Type error
# Constructor calls for non-specialized classes
assert_type(MyClass(1), MyClass[int])
assert_type(MyClass(1.0), MyClass[float])
If any class-scoped type variables are not solved when evaluating the __new__
method call using the supplied arguments, these type variables should be left
unsolved, allowing the __init__ method (if applicable) to be used to solve
them.
class MyClass[T]:
def __new__(cls, *args, **kwargs) -> Self:
return super().__new__(cls)
def __init__(self, x: T) -> None:
pass
assert_type(MyClass(1), MyClass[int])
assert_type(MyClass(""), MyClass[str])
For most classes, the return type for the __new__ method is typically
Self, but other types are also allowed. For example, the __new__
method may return an instance of a subclass or an instance of some completely
unrelated class.
If the evaluated return type of __new__ is not the class being constructed
(or a subclass thereof), a type checker should assume that the __init__
method will not be called. This is consistent with the runtime behavior of the
type.__call__ method. If the __new__ method return type is a union with
one or more members that are not the class being constructed (or a subclass
thereof), a type checker should likewise assume that the __init__ method
will not be called.
class MyClass:
def __new__(cls) -> int:
return 0
# In this case, the __init__ method should not be considered
# by the type checker when evaluating a constructor call.
def __init__(self, x: int):
pass
assert_type(MyClass(), int)
For purposes of this test, an explicit return type of Any (or a
union containing Any) should be treated as a type that is not an instance
of the class being constructed.
class MyClass:
def __new__(cls) -> Any:
return 0
# The __init__ method will not be called in this case, so
# it should not be evaluated.
def __init__(self, x: int):
pass
assert_type(MyClass(), Any)
If the return type of __new__ is not annotated, a type checker may assume
that the return type is Self and proceed with the assumption that the
__init__ method will be called.
If the class is generic, it is possible for a __new__ method to override
the specialized class type and return a class instance that is specialized
with different type arguments.
class MyClass[T]:
def __new__(cls, *args, **kwargs) -> "MyClass[list[T]]":
...
assert_type(MyClass[int](), MyClass[list[int]])
If the cls parameter within the __new__ method is not annotated, type
checkers should infer a type of type[Self]. Regardless of whether the
type of the cls parameter is explicit or inferred, the type checker should
bind the class being constructed to the cls parameter and report any type
errors that arise during binding.
class MyClass[T]:
def __new__(cls: "type[MyClass[int]]") -> "MyClass[int]": ...
MyClass() # OK
MyClass[int]() # OK
MyClass[str]() # Type Error
After evaluating the __new__ method, a type checker should evaluate the
__init__ method (if applicable) using the supplied arguments. If the class
is generic and explicitly specialized (or specialized via the __new__ method
return type), the type checker should partially specialize the __init__
method using the supplied type arguments. If the class is not explicitly
specialized, class-scoped type variables should be solved using the supplied
arguments passed to the constructor call.
This step should be skipped if the class does not define an __init__ method
and does not inherit an __init__ method from a base class other than
object.
class MyClass[T]:
def __init__(self, x: T) -> None:
...
# Constructor calls for specialized classes
assert_type(MyClass[int](1), MyClass[int])
assert_type(MyClass[float](1), MyClass[float])
MyClass[int](1.0) # Type error
# Constructor calls for non-specialized classes
assert_type(MyClass(1), MyClass[int])
assert_type(MyClass(1.0), MyClass[float])
If the self parameter within the __init__ method is not annotated, type
checkers should infer a type of Self. Regardless of whether the self
parameter type is explicit or inferred, a type checker should bind the class
being constructed to this parameter and report any type errors that arise
during binding.
class MyClass[T]:
def __init__(self: "MyClass[int]") -> None: ...
MyClass() # OK
MyClass[int]() # OK
MyClass[str]() # Type Error
The return type for __init__ is always None, which means the
method cannot influence the return type of the constructor call by specifying
a return type. There are cases where it is desirable for the __init__ method
to influence the return type, especially when the __init__ method is
overloaded. To enable this, type checkers should allow the self parameter
to be annotated with a type that influences the resulting type of the
constructor call.
class MyClass1[T]:
@overload
def __init__(self: "MyClass1[list[int]]", value: int) -> None: ...
@overload
def __init__(self: "MyClass1[set[str]]", value: str) -> None: ...
@overload
def __init__(self, value: T) -> None: ...
assert_type(MyClass1(0), MyClass1[list[int]])
assert_type(MyClass1[int](3), MyClass1[int])
assert_type(MyClass1(""), MyClass1[set[str]])
assert_type(MyClass1(3.0), MyClass1[float])
Function-scoped type variables can also be used in the self
annotation of an __init__ method to influence the return type of the
constructor call.
class MyClass2[T1, T2]:
def __init__[V1, V2](self: "MyClass2[V1, V2]", value1: V1, value2: V2) -> None: ...
assert_type(MyClass2(0, ""), MyClass2[int, str])
assert_type(MyClass2[int, str](0, ""), MyClass2[int, str])
class MyClass3[T1, T2]:
def __init__[V1, V2](self: "MyClass3[V2, V1]", value1: V1, value2: V2) -> None: ...
assert_type(MyClass3(0, ""), MyClass3[str, int])
assert_type(MyClass3[str, int](0, ""), MyClass3[str, int])
Class-scoped type variables should not be used in the self annotation
because such use can lead to ambiguous or nonsensical type evaluation results.
Type checkers should report an error if a class-scoped type variable is used
within a type annotation for the self parameter in an __init__ method.
class MyClass4[T1, T2]:
# The ``self`` annotation should result in a type error
def __init__(self: "MyClass4[T2, T1]") -> None: ...
If a class does not define a __new__ method or __init__ method and
does not inherit either of these methods from a base class other than
object, a type checker should evaluate the argument list using the
__new__ and __init__ methods from the object class.
class MyClass5:
pass
MyClass5() # OK
MyClass5(1) # Type error
When a value of type type[T] (where T is a concrete class or a type
variable) is called, a type checker should evaluate the constructor call as if
it is being made on the class T (or the class that represents the upper bound
of type variable T). This means the type checker should use the __call__
method of T's metaclass and the __new__ and __init__ methods of T
to evaluate the constructor call.
It should be noted that such code could be unsafe because the type type[T]
may represent subclasses of T, and those subclasses could redefine the
__new__ and __init__ methods in a way that is incompatible with the
base class. Likewise, the metaclass of T could redefine the __call__
method in a way that is incompatible with the base metaclass.
As discussed above, if a class is generic and not explicitly specialized, its
type variables should be solved using the arguments passed to the __new__
and __init__ methods. If one or more type variables are not solved during
these method evaluations, they should take on their default values.
from typing import Any, Self, assert_type
class MyClass1[T1, T2]:
def __new__(cls, x: T1) -> Self: ...
assert_type(MyClass1(1), MyClass1[int, Any])
class MyClass2[T1, T3 = str]:
def __new__(cls, x: T1) -> Self: ...
assert_type(MyClass2(1), MyClass2[int, str])
Type checkers may optionally validate that the __new__ and __init__
methods for a class have :term:`consistent` signatures.
class MyClass:
def __new__(cls) -> Self:
return super().__new__(cls)
# Type error: __new__ and __init__ have inconsistent signatures
def __init__(self, x: str) -> None:
pass
Class objects are callable, which means the type of a class object can be :term:`assignable` to a callable type.
def accepts_callable[**P, R](cb: Callable[P, R]) -> Callable[P, R]:
return cb
class MyClass:
def __init__(self, x: int) -> None:
pass
reveal_type(accepts_callable(MyClass)) # ``def (x: int) -> MyClass``
When converting a class to a callable type, a type checker should use the following rules, which reflect the same rules specified above for evaluating constructor calls:
- If the class has a custom metaclass that defines a
__call__method that is annotated with a return type other than a subclass of the class being constructed (or a union that contains such a type), a type checker should assume that the metaclass__call__method is overridingtype.__call__in some special manner. In this case, the callable should be synthesized from the parameters and return type of the metaclass__call__method after it is bound to the class, and the__new__or__init__methods (if present) should be ignored. This is an uncommon case. In the more typical case where there is no custom metaclass that overridestype.__call__in a special manner, the metaclass__call__signature should be ignored for purposes of converting to a callable type. If a custom metaclass__call__method is present but does not have an annotated return type, type checkers may assume that the method acts liketype.__call__and proceed to the next step. - If the class defines a
__new__method or inherits a__new__method from a base class other thanobject, a type checker should synthesize a callable from the parameters and return type of that method after it is bound to the class. - If the return type of the method in step 2 evaluates to a type that is not a
subclass of the class being constructed (or a union that includes such a
class), the final callable type is based on the result of step 2, and the
conversion process is complete. The
__init__method is ignored in this case. This is consistent with the runtime behavior of thetype.__call__method. - If the class defines an
__init__method or inherits an__init__method from a base class other thanobject, a callable type should be synthesized from the parameters of the__init__method after it is bound to the class instance resulting from step 2. The return type of this synthesized callable should be the concrete value ofSelf. - If step 2 and 4 both produce no result because the class does not define or
inherit a
__new__or__init__method from a class other thanobject, the type checker should synthesize callable types from the__new__and__init__methods for theobjectclass. - Steps 2, 4 and 5 will produce either one or two callable types. The final
result of the conversion process is the union of these types. This will
reflect the callable signatures of the applicable
__new__and__init__methods.
class A:
""" No __new__ or __init__ """
pass
class B:
""" __new__ and __init__ """
def __new__(cls, *args, **kwargs) -> Self:
...
def __init__(self, x: int) -> None:
...
class C:
""" __new__ but no __init__ """
def __new__(cls, x: int) -> int:
...
class CustomMeta(type):
def __call__(cls) -> NoReturn:
raise NotImplementedError("Class not constructable")
class D(metaclass=CustomMeta):
""" Custom metaclass that overrides type.__call__ """
def __new__(cls, *args, **kwargs) -> Self:
""" This __new__ is ignored for purposes of conversion """
pass
class E:
""" __new__ that causes __init__ to be ignored """
def __new__(cls) -> A:
return A.__new__(cls)
def __init__(self, x: int) -> None:
""" This __init__ is ignored for purposes of conversion """
...
reveal_type(accepts_callable(A)) # ``def () -> A``
reveal_type(accepts_callable(B)) # ``def (*args, **kwargs) -> B | def (x: int) -> B``
reveal_type(accepts_callable(C)) # ``def (x: int) -> int``
reveal_type(accepts_callable(D)) # ``def () -> NoReturn``
reveal_type(accepts_callable(E)) # ``def () -> A``
If the __init__ or __new__ method is overloaded, the callable
type should be synthesized from the overloads. The resulting callable type
itself will be overloaded.
class MyClass:
@overload
def __init__(self, x: int) -> None: ...
@overload
def __init__(self, x: str) -> None: ...
reveal_type(accepts_callable(MyClass)) # overload of ``def (x: int) -> MyClass`` and ``def (x: str) -> MyClass``
If the class is generic, the synthesized callable should include any class-scoped
type parameters that appear within the signature, but these type parameters should
be converted to function-scoped type parameters for the callable.
Any function-scoped type parameters in the __init__ or __new__
method should also be included as function-scoped type parameters in the synthesized
callable.
class MyClass[T]:
def __init__[V](self, x: T, y: list[V], z: V) -> None: ...
reveal_type(accepts_callable(MyClass)) # ``def [T, V] (x: T, y: list[V], z: V) -> MyClass[T]``
A class object is itself an instance of its :term:`python:metaclass`, so the creation of a class is also a constructor call, one made on the metaclass. While the sections above describe how a metaclass participates in the construction of instances of a class, the following sections describe the construction of class objects themselves.
A metaclass constructor is invoked in one of two ways:
- Directly, by calling the metaclass with a class name, a tuple of base
classes, and a namespace dictionary (for example,
Meta(name, bases, namespace)), optionally along with additional keyword arguments. - Implicitly, by a :keyword:`python:class` statement, which assembles these three arguments from the statement and the class body and then calls the metaclass.
In both cases, the metaclass call should be evaluated using the same rules described in the sections above: the :meth:`!__call__` method of the metaclass's own metaclass (typically :meth:`!type.__call__`) is invoked, which in turn calls the :meth:`!__new__` and :meth:`!__init__` methods of the metaclass. These methods are typically inherited from :class:`type`, whose type definitions require special handling by type checkers, as described below.
The following example illustrates these rules applied to metaclass calls:
class MetaMeta(type):
def __call__(cls, *args, **kwargs) -> Never:
raise TypeError("Classes cannot be created with this metaclass")
class Meta1(type, metaclass=MetaMeta):
pass
# The __call__() method of the metaclass's own metaclass is evaluated first:
assert_type(Meta1("A", (), {}), Never)
class Meta2(type):
def __new__(
mcls,
name: str,
bases: tuple[type, ...],
namespace: dict[str, Any],
*,
key: int,
):
return super().__new__(mcls, name, bases, namespace)
# Then, the __new__ and __init__ methods of the metaclass are evaluated:
Meta2("B", (), {}, key=1) # OK, evaluates to an instance of Meta2
Meta2("B", (), {}) # Type error: missing argument "key"
class Meta3(type):
def __new__(
mcls, name: str, bases: tuple[type, ...], namespace: dict[str, Any]
) -> int:
return 0
# Not evaluated, as __new__ does not return an instance of Meta3:
def __init__(cls, x: str) -> None:
pass
assert_type(Meta3("C", (), {}), int)
In addition to being the default metaclass, :class:`type` serves a second purpose: when called with a single argument, it returns the type of that argument rather than creating a new class. :class:`type` therefore supports two distinct call forms, which are distinguished by the number of positional arguments:
type(obj, /)returns the class ofobj.type(name, bases, dict, /, **kwds)creates and returns a new class.
These two forms are typically declared as overloads of the :meth:`!__new__` and :meth:`!__init__` methods in the type definition of :class:`type`. Both forms require special-case handling by type checkers.
Although the single-argument form is typically declared with a return type of
type, type checkers should special-case this form and evaluate its result
as type[T], where T is the type of the argument.
def func(x: int, y: int | str) -> None:
assert_type(type(x), type[int])
assert_type(type(y), type[int] | type[str])
At runtime, the single-argument form applies only when the class being called is :class:`type` itself, and is not inherited by metaclasses: a single-argument call to a subclass of :class:`type` raises a :exc:`TypeError`.
class Meta(type):
pass
assert_type(type(1), type[int]) # OK, uses the single-argument form
Meta(1) # Type error: single-argument form does not apply to subclasses
Meta("A", (), {}) # OK, uses the three-argument form
This special-casing applies only to the :meth:`!__new__` and :meth:`!__init__` methods inherited from :class:`type`. If a metaclass defines its own :meth:`!__new__` method that accepts a single argument, calls to it should be evaluated using the rules for regular constructor calls described earlier in this chapter.
The evaluated return type of the three-argument form is an instance of the metaclass being called, consistent with the return type definition of :meth:`!type.__new__`. Type checkers may infer a more precise type for the returned class object, for example, one equivalent to a class defined by a :keyword:`class` statement with the given name, base classes, and namespace.
When a :keyword:`class` statement is executed, the runtime performs the following steps to create the new class object (see :ref:`python:metaclasses`):
- The metaclass is determined. If a
metaclasskeyword argument is present in the class statement's argument list, it is used as a candidate; otherwise, :class:`type` is. The most derived metaclass among the candidate and the metaclasses of all base classes is selected. If no candidate is a (non-strict) subclass of all of the others, a :exc:`TypeError` is raised (see :ref:`py315:metaclass-determination`). - The class namespace is prepared. If the metaclass has a :attr:`!__prepare__`
attribute, it is called as
Meta.__prepare__(name, bases, **kwds), and its result is used as the namespace object. - The class body is executed within this namespace.
- The metaclass is called as
Meta(name, bases, namespace, **kwds), wherekwdsconsists of the keyword arguments that appear in the class statement's argument list, excludingmetaclassitself.
Type checkers may report an error for a class statement whose base classes have incompatible metaclasses.
Type checkers should validate keyword arguments in a class statement's
argument list (other than metaclass) by evaluating the implied metaclass
call using the constructor call rules described in :ref:`constructor-calls`.
class Meta(type):
def __new__(
mcls,
name: str,
bases: tuple[type, ...],
namespace: dict[str, Any],
*,
key: int,
):
return super().__new__(mcls, name, bases, namespace)
class MyClass1(metaclass=Meta, key=3): # OK
pass
class MyClass2(metaclass=Meta, key=""): # Type error: wrong type for "key"
pass
class MyClass3(metaclass=Meta): # Type error: missing argument "key"
pass
Meta("MyClass4", (), {}, key=3) # OK
Meta("MyClass5", (), {}, key="") # Type error: wrong type for "key"
Keyword arguments in a direct metaclass call (such as the last two calls in the example above) require no special handling: they are validated as part of evaluating the call using the standard constructor call rules.
Type checkers should honor the evaluated retunr type of the implied metaclass call, even if the evaluated type isn't a class:
class Meta(type):
def __new__(cls, *args: object, **kwargs: obect) -> int:
return 1
class MyClass6(metaclass=Meta):
pass
assert_type(MyClass6, int)
Type checkers may validate the implied call to :attr:`!__prepare__`:
class Meta(type):
@classmethod
def __prepare__(mcls, name: str, bases: tuple[type, ...]): # No **kwds
return {}
def __new__(
mcls,
name: str,
bases: tuple[type, ...],
namespace: dict[str, Any],
*,
key: int,
):
return super().__new__(mcls, name, bases, namespace)
# The 'key' argument may result in a type checker error:
class MyClass6(metaclass=Meta, key=3):
pass
The metaclass argument can also be an arbitrary callable that is not a subclass
of :class:`type`. Support for this pattern is currently unspecified.
:meth:`!type.__new__` invokes the :meth:`~object.__init_subclass__`
method of the parent class (the class that follows the newly created class in
its :term:`python:method resolution order`) passing the newly created class as
cls along with the keyword arguments supplied to the metaclass constructor
(see :ref:`python:class-customization`).
:meth:`~object.__init_subclass__` is implicitly a class method: it is converted to a :class:`classmethod` even when it is not explicitly decorated as one, and it is not called for the class that defines it, only for its subclasses. Type checkers should treat it as a classmethod if it isn't explicitly defined as one.
If the metaclass of the class being defined does not define its own :meth:`!__new__` method (including when no explicit metaclass is specified), type checkers should validate the keyword arguments in a class statement's argument list against the :meth:`~object.__init_subclass__` method of the parent class.
class Base:
def __init_subclass__(cls, *, flag: bool = False) -> None:
super().__init_subclass__()
class MyClass1(Base, flag=True): # OK
pass
class MyClass2(Base, flag=""): # Type error: wrong type for "flag"
pass
class MyClass3(Base, other=1): # Type error: Base.__init_subclass__() got an unexpected keyword argument 'other'
pass
class MyClass4(other=1): # Type error: MyClass4.__init_subclass__() takes no keyword arguments
pass
A metaclass :meth:`!__init__` method has no effect on this rule: when the metaclass does not define its own :meth:`!__new__` method, :meth:`!type.__new__` still forwards the keyword arguments to :meth:`~object.__init_subclass__`, so the keyword arguments should satisfy both the metaclass :meth:`!__init__` method (as part of validating the implied metaclass call) and the :meth:`~object.__init_subclass__` method of the parent class.
class MetaInit(type):
def __init__(
cls,
name: str,
bases: tuple[type, ...],
namespace: dict[str, Any],
*,
key: int,
) -> None:
super().__init__(name, bases, namespace)
# Type error: "key" is accepted by MetaInit.__init__(), but type.__new__()
# forwards it to Base.__init_subclass__(), which does not accept it:
class MyClass5(Base, metaclass=MetaInit, key=1):
pass
The same forwarding occurs when the metaclass is called directly:
type("D", (Base,), {}, flag=True) passes flag to
:meth:`!Base.__init_subclass__`. Type checkers may validate keyword
arguments in such calls against the :meth:`~object.__init_subclass__` method of
the parent class when the base classes can be statically determined.
If the metaclass defines its own :meth:`!__new__` method that accepts keyword
arguments only through a **kwargs parameter, whether these arguments are
forwarded to :meth:`!type.__new__` (and from there to
:meth:`~object.__init_subclass__`) cannot generally be determined statically.
In this situation, type checkers may additionally validate the keyword
arguments against the :meth:`~object.__init_subclass__` method of the parent
class.