Differences between revisions 1 and 2
Revision 1 as of 2023-01-06 18:56:11
Size: 2429
Comment:
Revision 2 as of 2023-01-06 18:57:38
Size: 2427
Comment:
Deletions are marked like this. Additions are marked like this.
Line 5: Line 5:
The type annotation system has evolved rapidly with multiple instances of breaking changes. For an overview of the entire system, see [[Python/TypeAnnotations|Type Annotations]]. The type annotation system has evolved rapidly with multiple instances of breaking changes. For an overview of the entire system, see [[Python/TypeAnnotation|Type Annotation]].

Python Typing

The typing and typing_extensions modules support the type annotation system in the Python language.

The type annotation system has evolved rapidly with multiple instances of breaking changes. For an overview of the entire system, see Type Annotation.


Primitive Types

Any satisfies all type checking.

For functions that should never return or should never be called, use Never.

from typing import Never

def never_call_me(arg: Never) -> None:
    pass

# fail
def do_it_anyway(arg: int | str) -> None:
    never_call_me(arg)

# pass: arg is either int or str so the default case is never reached
def int_or_str(arg: int | str) -> None:
    match arg:
        case int():
            pass
        case str():
            pass
        case _:
            never_call_me(arg)

For class methods that return an instance of the class, use Self.

from typing import Self

class Foo:
    def return_self(self) -> Self:
        return self

Deprecations

Do not use typing.Tuple[...] in Python 3.9+; instead use the built-in tuple[...].

Do not use typing.Callable[...] in Python 3.9+; instead use collections.abc.Callable[...].

Do not use NoReturn in Python 3.11+; instead use Never.


Custom Types

To create a custom type, use NewType. Type checkers will treat the custom type as a subclass of the original type, while rejecting passed arguments of the original type.

from typing import NewType

UserId = NewType('UserId', int)

# passes
user_a = get_user_name(UserId(42351))

# fails
user_b = get_user_name(-1)

Given the above example, at runtime, UserId returns a callable that immediately returns the original value. This leads to three properties:

  1. UserId(value) has minimal runtime overhead

  2. an instance of UserId cannot be returned at runtime; UserId(value) immediately evaluates to value

  3. UserId is not subclassable (except by chaining NewType: ProUserId = NewType('ProUserId', UserId))


Generics

To annotate a generic type, use TypeVar.

from collections.abc import Sequence
from typing import TypeVar

T = TypeVar('T')

def first(l: Sequence[T]) -> T:
    return l[0]


CategoryRicottone

Python/Typing (last edited 2023-04-20 14:07:06 by DominicRicottone)