Type annotations

The meaning of annotations

The type system leveragesPEP 3107-style annotations with a number ofextensions described in sections below. In its basic form, typehinting is used by filling function annotation slots with classes:

defgreeting(name:str)->str:return'Hello '+name

This states that the expected type of thename argument isstr. Analogically, the expected return type isstr.

Expressions whose type isassignable to a specific argument type arealso accepted for that argument. Similarly, an expression whose type isassignable to the annotated return type can be returned from the function.

Any function without annotations can be treated as havingAnyannotations on all arguments and the return type. Type checkers may alsooptionally infer more precise types for missing annotations.

Type checkers may choose to entirely ignore (not type check) the bodies offunctions with no annotations, but this behavior is not required.

It is recommended but not required that checked functions haveannotations for all arguments and the return type. For a checkedfunction, the default annotation for arguments and for the return typeisAny. An exception to the above is the first argument ofinstance and class methods (conventionally namedself orcls),which type checkers should assume to have an appropriate type, as perAnnotating instance and class methods.

(Note that the return type of__init__ ought to be annotated with->None. The reason for this is subtle. If__init__ assumeda return annotation of->None, would that mean that anargument-less, un-annotated__init__ method should still betype-checked? Rather than leaving this ambiguous or introducing anexception to the exception, we simply say that__init__ ought tohave a return annotation; the default behavior is thus the same as forother methods.)

A type checker is expected to check the body of a checked function forconsistency with the given annotations. The annotations may also beused to check correctness of calls appearing in other checked functions.

Type checkers are expected to attempt to infer as much information asnecessary. The minimum requirement is to handle the builtindecorators@property,@staticmethod and@classmethod.

Type and annotation expressions

The termstype expression andannotation expression denote specificsubsets of Python expressions that are used in the type system. Alltype expressions are also annotation expressions, but not all annotationexpressions are type expressions.

Atype expression is any expression that validly expresses a type. Typeexpressions are always acceptable in annotations and also in various otherplaces. Specifically, type expressions are used in the following locations:

  • In a type annotation (always as part of an annotation expression)

  • The first argument tocast()

  • The second argument toassert_type()

  • The bounds and constraints of aTypeVar (whether created through theold syntax or the native syntax in Python 3.12)

  • The default of aTypeVar,ParamSpec, orTypeVarTuple (whethercreated through the old syntax or the native syntax in Python 3.12)

  • The definition of a type alias (whether created through thetype statement,the old assignment syntax, or theTypeAliasType constructor)

  • The type arguments of a generic class (which may appear in a base classor in a constructor call)

  • The definitions of fields in the functional forms for creatingTypedDict andNamedTuple types

  • The value passed to theextra_items argument in theTypedDictconstructor

  • The base type in the definition of aNewType

Anannotation expression is an expression that is acceptable to use inan annotation context (a function parameter annotation, function returnannotation, or variable annotation). Generally, an annotation expressionis a type expression, optionally surrounded by one or moretype qualifiersor byAnnotated. Each type qualifier is valid only in some contexts. Notethat while annotation expressions are the only expressions valid as typeannotations in the type system, the Python language itself makes no suchrestriction: any expression is allowed.

Annotations must be valid expressions that evaluate without raisingexceptions at the time the function is defined (but seeString annotations).

The following grammar describes the allowed elements of type and annotation expressions:

annotation_expression ::=  <Required> '['annotation_expression ']'                           | <NotRequired> '['annotation_expression ']'                           | <ReadOnly> '['annotation_expression']'                           | <ClassVar> ('['annotation_expression']')?                           | <Final> ('['annotation_expression']')?                           | <InitVar> '['annotation_expression ']'                           | <Annotated> '['annotation_expression ','                                         expression (',' expression)* ']'                           | <TypeAlias>                                 (valid only in variable annotations)                           |unpacked                                 (valid only for *args annotations)                           | <Unpack> '[' name ']'                                 (where name refers to an in-scope TypedDict;                                  valid only in **kwargs annotations)                           |string_annotation                                 (must evaluate to a validannotation_expression)                           | name '.' 'args'                                (where name must be an in-scope ParamSpec;                                 valid only in *args annotations)                           | name '.' 'kwargs'                                 (where name must be an in-scope ParamSpec;                                  valid only in **kwargs annotations)                           |type_expressiontype_expression ::=  <Any>                           | <Self>                                 (valid only in some contexts)                           | <LiteralString>                           | <NoReturn>                           | <Never>                           | <None>                           | name                                 (where name must refer to a valid in-scope class,                                  type alias, or TypeVar)                           | name '[' (maybe_unpacked |type_expression_list)                                  (',' (maybe_unpacked |type_expression_list))* ']'                                 (thetype_expression_list form is valid only when                                  specializing a ParamSpec)                           | name '[' '(' ')' ']'                                 (denoting specialization with an empty TypeVarTuple)                           | <Literal> '[' expression (',' expression) ']'                                 (see documentation for Literal for restrictions)                           |type_expression '|'type_expression                           | <Optional> '['type_expression ']'                           | <Union> '['type_expression (','type_expression)* ']'                           | <type> '[' <Any> ']'                           | <type> '[' name ']'                                 (where name must refer to a valid in-scope class                                  or TypeVar)                           | <Callable> '[' '...' ','type_expression ']'                           | <Callable> '[' name ','type_expression ']'                                 (where name must be a valid in-scope ParamSpec)                           | <Callable> '[' <Concatenate> '[' (type_expression ',')+                                        (name | '...') ']' ','type_expression ']'                                 (where name must be a valid in-scope ParamSpec)                           | <Callable> '[' '['maybe_unpacked (','maybe_unpacked)*                                        ']' ','type_expression ']'                           |tuple_type_expression                           | <Annotated> '['type_expression ','                                         expression (',' expression)* ']'                           | <TypeGuard> '['type_expression ']'                                 (valid only in some contexts)                           | <TypeIs> '['type_expression ']'                                 (valid only in some contexts)                           |string_annotation                                 (must evaluate to a validtype_expression)maybe_unpacked ::=type_expression |unpackedunpacked ::=  '*'unpackable                           | <Unpack> '['unpackable ']'unpackable ::=tuple_type_expression`                           | name                                 (where name must refer to an in-scope TypeVarTuple)tuple_type_expression ::=  <tuple> '[' '(' ')' ']'                                (representing an empty tuple)                           | <tuple> '['type_expression ',' '...' ']'                                 (representing an arbitrary-length tuple)                           | <tuple> '['maybe_unpacked (','maybe_unpacked)* ']'string_annotation ::=  string                               (must be a string literal that is parsable                                as Python code; see "String annotations")type_expression_list ::=  '['type_expression (','type_expression)* ']'                           | '[' ']'

Notes:

  • The grammar assumes the code has already been parsed as Python code, andloosely follows the structure of the AST. Syntactic details like commentsand whitespace are ignored.

  • <Name> refers to aspecial form. Most special forms must be importedfromtyping ortyping_extensions, except forNone,InitVar,type, andtuple. The latter two have aliases intyping:typing.Typeandtyping.Tuple.InitVar must be imported fromdataclasses.Callable may be imported from eithertyping orcollections.abc.Special forms may be aliased(e.g.,fromtypingimportLiteralasL), and they may be referred to by aqualified name (e.g.,typing.Literal). There are other special forms that are notacceptable in any annotation or type expression, includingGeneric,Protocol,andTypedDict.

  • Any leaf denoted asname may also be a qualified name (i.e.,module'.'nameorpackage'.'module'.'name, with any level of nesting).

  • Comments in parentheses denote additional restrictions not expressed in thegrammar, or brief descriptions of the meaning of a construct.

String annotations

When a type hint cannot be evaluated at runtime, thatdefinition may be expressed as a string literal, to be resolved later.

A situation where this occurs commonly is the definition of acontainer class, where the class being defined occurs in the signatureof some of the methods. For example, the following code (the start ofa simple binary tree implementation) does not work:

classTree:def__init__(self,left:Tree,right:Tree):self.left=leftself.right=right

To address this, we write:

classTree:def__init__(self,left:'Tree',right:'Tree'):self.left=leftself.right=right

The string literal should contain a valid Python expression (i.e.,compile(lit,'','eval') should be a valid code object) and itshould evaluate without errors once the module has been fully loaded.The local and global namespace in which it is evaluated should be thesame namespaces in which default arguments to the same function wouldbe evaluated.

Moreover, the expression should be parseable as a valid type hint, i.e.,it is constrained by the rules fromthe expression grammar.

If a triple quote is used, the string should be parsed as though it isimplicitly surrounded by parentheses. This allows newline characters to beused within the string literal:

value:"""    int |    str |    list[Any]"""

It is allowable to use string literals aspart of a type hint, forexample:

classTree:...defleaves(self)->list['Tree']:...

A common use for forward references is when e.g. Django models areneeded in the signatures. Typically, each model is in a separatefile, and has methods taking arguments whose type involves other models.Because of the way circular imports work in Python, it is often notpossible to import all the needed models directly:

# File models/a.pyfrommodels.bimportBclassA(Model):deffoo(self,b:B):...# File models/b.pyfrommodels.aimportAclassB(Model):defbar(self,a:A):...# File main.pyfrommodels.aimportAfrommodels.bimportB

Assuming main is imported first, this will fail with an ImportError atthe linefrommodels.aimportA in models/b.py, which is beingimported from models/a.py before a has defined class A. The solutionis to switch to module-only imports and reference the models by their_module_._class_ name:

# File models/a.pyfrommodelsimportbclassA(Model):deffoo(self,b:'b.B'):...# File models/b.pyfrommodelsimportaclassB(Model):defbar(self,a:'a.A'):...# File main.pyfrommodels.aimportAfrommodels.bimportB

Annotating generator functions and coroutines

The return type of generator functions can be annotated bythe generic typeGenerator[yield_type,send_type,return_type] provided bytyping.py module:

defecho_round()->Generator[int,float,str]:res=yield0whileres:res=yieldround(res)return'OK'

Coroutines introduced inPEP 492 are annotated with the same syntax asordinary functions. However, the return type annotation corresponds to thetype ofawait expression, not to the coroutine type:

asyncdefspam(ignored:int)->str:return'spam'asyncdeffoo()->None:bar=awaitspam(42)# type is str

The generic ABCcollections.abc.Coroutine can be usedto specify awaitables that also supportsend() andthrow() methods. The variance and order of type variablescorrespond to those ofGenerator, namelyCoroutine[T_co,T_contra,V_co],for example:

fromcollections.abcimportCoroutinec:Coroutine[list[str],str,int]...x=c.send('hi')# type is list[str]asyncdefbar()->None:x=awaitc# type is int

The generic ABCsAwaitable,AsyncIterable, andAsyncIterator can be used for situations where more precisetypes cannot be specified:

defop()->collections.abc.Awaitable[str]:ifcond:returnspam(42)else:returnasyncio.Future(...)

Annotating instance and class methods

In most cases the first argument of instance and class methods(conventionally namedself orcls) does not need to be annotated.

If the argument is not annotated, then for instance methods it may beinferred to have either the type of the containing class, or the typeSelf. For class methods it may be inferred to have either the type objecttype corresponding to the containing class object, ortype[Self].

In addition, the first argument in an instance method can be annotatedwith a type variable. In this case the return type may use the sametype variable, thus making that method a generic function. For example:

classCopyable:defcopy[T:Copyable](self:T)->T:# return a copy of selfclassC(Copyable):...c=C()c2=c.copy()# type here should be C

The same applies to class methods usingtype[] in an annotationof the first argument:

classC:@classmethoddeffactory[T:C](cls:type[T])->T:# make a new instance of clsclassD(C):...d=D.factory()# type here should be D

Note that some type checkers may apply restrictions on this use, such asrequiring an appropriate upper bound for the type variable used(see examples).