typing — Unterstützung für Typ-Hinweise

Hinzugefügt in Version 3.5.

Quellcode: Lib/typing.py

Hinweis

Die Python-Laufzeit erzwingt Funktions- und Variablen-Typannotationen nicht. Sie können von Drittanbieter-Tools wie Typüberprüfern, IDEs, Lintern usw. verwendet werden.


Dieses Modul bietet Laufzeitunterstützung für Typ-Hinweise.

Betrachten Sie die folgende Funktion

def surface_area_of_cube(edge_length: float) -> str:
    return f"The surface area of the cube is {6 * edge_length ** 2}."

Die Funktion surface_area_of_cube nimmt ein Argument, das als Instanz von float erwartet wird, wie durch den Typ-Hinweis edge_length: float angezeigt. Die Funktion soll eine Instanz von str zurückgeben, wie durch den -> str Hinweis angezeigt.

Typ-Hinweise können einfache Klassen wie float oder str sein, sie können aber auch komplexer sein. Das Modul typing bietet ein Vokabular für fortgeschrittenere Typ-Hinweise.

Neue Funktionen werden häufig zum Modul typing hinzugefügt. Das Paket typing_extensions bietet Backports dieser neuen Funktionen für ältere Python-Versionen.

Siehe auch

Typing-Cheat-Sheet

Ein kurzer Überblick über Typ-Hinweise (gehostet in der mypy-Dokumentation)

Abschnitt „Type System Reference“ in der mypy-Dokumentation

Das Python-Typensystem ist über PEPs standardisiert, daher sollte sich dieser Referenzabschnitt grob auf die meisten Python-Typüberprüfer anwenden lassen. (Einige Teile können immer noch mypy-spezifisch sein.)

Statische Typisierung mit Python

Typüberprüfer-agnostische Dokumentation, geschrieben von der Community, die Typensystemfunktionen, nützliche typbezogene Werkzeuge und Best Practices für die Typisierung detailliert beschreibt.

Spezifikation für das Python-Typensystem

Die kanonische, aktuelle Spezifikation des Python-Typensystems finden Sie unter Spezifikation für das Python-Typensystem.

Typ-Aliase

Ein Typ-Alias wird mit der type-Anweisung definiert, die eine Instanz von TypeAliasType erstellt. In diesem Beispiel werden Vector und list[float] von statischen Typüberprüfern gleichwertig behandelt.

type Vector = list[float]

def scale(scalar: float, vector: Vector) -> Vector:
    return [scalar * num for num in vector]

# passes type checking; a list of floats qualifies as a Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])

Typ-Aliase sind nützlich, um komplexe Typsignaturen zu vereinfachen. Zum Beispiel

from collections.abc import Sequence

type ConnectionOptions = dict[str, str]
type Address = tuple[str, int]
type Server = tuple[Address, ConnectionOptions]

def broadcast_message(message: str, servers: Sequence[Server]) -> None:
    ...

# The static type checker will treat the previous type signature as
# being exactly equivalent to this one.
def broadcast_message(
    message: str,
    servers: Sequence[tuple[tuple[str, int], dict[str, str]]]
) -> None:
    ...

Die type-Anweisung ist neu in Python 3.12. Aus Gründen der Abwärtskompatibilität können Typ-Aliase auch durch einfache Zuweisung erstellt werden.

Vector = list[float]

Oder mit TypeAlias markiert, um explizit zu machen, dass es sich um einen Typ-Alias und nicht um eine normale Variablenszuweisung handelt.

from typing import TypeAlias

Vector: TypeAlias = list[float]

NewType

Verwenden Sie die Hilfsfunktion NewType, um eindeutige Typen zu erstellen.

from typing import NewType

UserId = NewType('UserId', int)
some_id = UserId(524313)

Der statische Typüberprüfer behandelt den neuen Typ so, als wäre er eine Unterklasse des ursprünglichen Typs. Dies ist hilfreich, um logische Fehler abzufangen.

def get_user_name(user_id: UserId) -> str:
    ...

# passes type checking
user_a = get_user_name(UserId(42351))

# fails type checking; an int is not a UserId
user_b = get_user_name(-1)

Sie können immer noch alle int-Operationen auf einer Variablen vom Typ UserId ausführen, aber das Ergebnis wird immer vom Typ int sein. Dies ermöglicht es Ihnen, UserId überall dort zu übergeben, wo ein int erwartet werden könnte, verhindert aber, dass Sie versehentlich eine UserId auf ungültige Weise erstellen.

# 'output' is of type 'int', not 'UserId'
output = UserId(23413) + UserId(54341)

Beachten Sie, dass diese Prüfungen nur vom statischen Typüberprüfer erzwungen werden. Zur Laufzeit macht die Anweisung Derived = NewType('Derived', Base) Derived zu einem aufrufbaren Objekt, das sofort den übergebenen Parameter zurückgibt. Das bedeutet, dass der Ausdruck Derived(some_value) keine neue Klasse erstellt und über den einer regulären Funktionsaufrufs hinaus keinen erheblichen Overhead verursacht.

Genauer gesagt ist der Ausdruck some_value is Derived(some_value) zur Laufzeit immer wahr.

Es ist ungültig, eine Unterklasse von Derived zu erstellen.

from typing import NewType

UserId = NewType('UserId', int)

# Fails at runtime and does not pass type checking
class AdminUserId(UserId): pass

Es ist jedoch möglich, ein NewType basierend auf einem „abgeleiteten“ NewType zu erstellen.

from typing import NewType

UserId = NewType('UserId', int)

ProUserId = NewType('ProUserId', UserId)

und die Typüberprüfung für ProUserId funktioniert wie erwartet.

Weitere Details finden Sie in PEP 484.

Hinweis

Denken Sie daran, dass die Verwendung eines Typ-Alias angibt, dass zwei Typen gleichwertig zueinander sind. Wenn Sie type Alias = Original verwenden, behandelt der statische Typüberprüfer Alias in allen Fällen als exakt gleichwertig zu Original. Dies ist nützlich, wenn Sie komplexe Typsignaturen vereinfachen möchten.

Im Gegensatz dazu erklärt NewType einen Typ als Untertyp eines anderen. Wenn Sie Derived = NewType('Derived', Original) verwenden, behandelt der statische Typüberprüfer Derived als Unterklasse von Original, was bedeutet, dass ein Wert vom Typ Original nicht an Stellen verwendet werden kann, an denen ein Wert vom Typ Derived erwartet wird. Dies ist nützlich, wenn Sie logische Fehler mit minimalen Laufzeitkosten verhindern möchten.

Hinzugefügt in Version 3.5.2.

Geändert in Version 3.10: NewType ist jetzt eine Klasse und keine Funktion mehr. Daher gibt es beim Aufruf von NewType einen zusätzlichen Laufzeitaufwand im Vergleich zu einer regulären Funktion.

Geändert in Version 3.11: Die Leistung beim Aufruf von NewType wurde auf das Niveau von Python 3.9 zurückgesetzt.

Annotation von aufrufbaren Objekten

Funktionen – oder andere aufrufbare Objekte – können mit collections.abc.Callable oder dem veralteten typing.Callable annotiert werden. Callable[[int], str] bezeichnet eine Funktion, die einen einzelnen Parameter vom Typ int nimmt und einen str zurückgibt.

Zum Beispiel

from collections.abc import Callable, Awaitable

def feeder(get_next_item: Callable[[], str]) -> None:
    ...  # Body

def async_query(on_success: Callable[[int], None],
                on_error: Callable[[int, Exception], None]) -> None:
    ...  # Body

async def on_update(value: str) -> None:
    ...  # Body

callback: Callable[[str], Awaitable[None]] = on_update

Die Abonnement-Syntax muss immer mit genau zwei Werten verwendet werden: der Argumentliste und dem Rückgabetyp. Die Argumentliste muss eine Liste von Typen, ein ParamSpec, Concatenate oder ein Ellipse (...) sein. Der Rückgabetyp muss ein einzelner Typ sein.

Wenn eine literale Ellipse ... als Argumentliste angegeben wird, bedeutet dies, dass ein aufrufbares Objekt mit beliebiger Parameterliste akzeptabel wäre.

def concat(x: str, y: str) -> str:
    return x + y

x: Callable[..., str]
x = str     # OK
x = concat  # Also OK

Callable kann keine komplexen Signaturen ausdrücken, wie z. B. Funktionen, die eine variable Anzahl von Argumenten akzeptieren, überladene Funktionen oder Funktionen mit nur Schlüsselwortparametern. Diese Signaturen können jedoch durch Definition einer Protocol-Klasse mit einer __call__()-Methode ausgedrückt werden.

from collections.abc import Iterable
from typing import Protocol

class Combiner(Protocol):
    def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ...

def batch_proc(data: Iterable[bytes], cb_results: Combiner) -> bytes:
    for item in data:
        ...

def good_cb(*vals: bytes, maxlen: int | None = None) -> list[bytes]:
    ...
def bad_cb(*vals: bytes, maxitems: int | None) -> list[bytes]:
    ...

batch_proc([], good_cb)  # OK
batch_proc([], bad_cb)   # Error! Argument 2 has incompatible type because of
                         # different name and kind in the callback

Aufrufbare Objekte, die andere aufrufbare Objekte als Argumente akzeptieren, können mit ParamSpec angeben, dass ihre Parametertypen voneinander abhängig sind. Wenn dieses aufrufbare Objekt zusätzliche Argumente hinzufügt oder entfernt, kann der Concatenate-Operator verwendet werden. Sie haben die Form Callable[ParamSpecVariable, ReturnType] bzw. Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType].

Geändert in Version 3.10: Callable unterstützt jetzt ParamSpec und Concatenate. Weitere Details finden Sie in PEP 612.

Siehe auch

Die Dokumentation für ParamSpec und Concatenate enthält Beispiele für die Verwendung in Callable.

Generics

Da Typinformationen über Objekte, die in Containern gespeichert sind, nicht generisch statisch abgeleitet werden können, unterstützen viele Containerklassen in der Standardbibliothek die Abonnementfunktion, um die erwarteten Typen von Containerelementen anzugeben.

from collections.abc import Mapping, Sequence

class Employee: ...

# Sequence[Employee] indicates that all elements in the sequence
# must be instances of "Employee".
# Mapping[str, str] indicates that all keys and all values in the mapping
# must be strings.
def notify_by_email(employees: Sequence[Employee],
                    overrides: Mapping[str, str]) -> None: ...

Generische Funktionen und Klassen können durch Verwendung der Typ-Parameter-Syntax parametrisiert werden.

from collections.abc import Sequence

def first[T](l: Sequence[T]) -> T:  # Function is generic over the TypeVar "T"
    return l[0]

Oder durch direkte Verwendung der TypeVar-Fabrik.

from collections.abc import Sequence
from typing import TypeVar

U = TypeVar('U')                  # Declare type variable "U"

def second(l: Sequence[U]) -> U:  # Function is generic over the TypeVar "U"
    return l[1]

Geändert in Version 3.12: Syntaktische Unterstützung für Generics ist neu in Python 3.12.

Annotation von Tupeln

Für die meisten Container in Python geht das Typsystem davon aus, dass alle Elemente im Container vom selben Typ sind. Zum Beispiel

from collections.abc import Mapping

# Type checker will infer that all elements in ``x`` are meant to be ints
x: list[int] = []

# Type checker error: ``list`` only accepts a single type argument:
y: list[int, str] = [1, 'foo']

# Type checker will infer that all keys in ``z`` are meant to be strings,
# and that all values in ``z`` are meant to be either strings or ints
z: Mapping[str, str | int] = {}

list akzeptiert nur ein Typargument, sodass ein Typüberprüfer einen Fehler bei der y-Zuweisung oben melden würde. Ebenso akzeptiert Mapping nur zwei Typargumente: Das erste gibt den Typ der Schlüssel und das zweite den Typ der Werte an.

Im Gegensatz zu den meisten anderen Python-Containern ist es in idiomatischem Python-Code jedoch üblich, dass Tupel Elemente enthalten, die nicht alle vom selben Typ sind. Aus diesem Grund werden Tupel in Pythons Typsystem speziell behandelt. tuple akzeptiert beliebig viele Typargumente.

# OK: ``x`` is assigned to a tuple of length 1 where the sole element is an int
x: tuple[int] = (5,)

# OK: ``y`` is assigned to a tuple of length 2;
# element 1 is an int, element 2 is a str
y: tuple[int, str] = (5, "foo")

# Error: the type annotation indicates a tuple of length 1,
# but ``z`` has been assigned to a tuple of length 3
z: tuple[int] = (1, 2, 3)

Um ein Tupel zu bezeichnen, das beliebige Länge haben kann und in dem alle Elemente vom Typ T sind, verwenden Sie die literale Ellipse ...: tuple[T, ...]. Um ein leeres Tupel zu bezeichnen, verwenden Sie tuple[()]. Die Verwendung von tuple allein als Annotation ist äquivalent zur Verwendung von tuple[Any, ...].

x: tuple[int, ...] = (1, 2)
# These reassignments are OK: ``tuple[int, ...]`` indicates x can be of any length
x = (1, 2, 3)
x = ()
# This reassignment is an error: all elements in ``x`` must be ints
x = ("foo", "bar")

# ``y`` can only ever be assigned to an empty tuple
y: tuple[()] = ()

z: tuple = ("foo", "bar")
# These reassignments are OK: plain ``tuple`` is equivalent to ``tuple[Any, ...]``
z = (1, 2, 3)
z = ()

Der Typ von Klassenobjekten

Eine Variable, die mit C annotiert ist, kann einen Wert vom Typ C akzeptieren. Im Gegensatz dazu kann eine Variable, die mit type[C] (oder dem veralteten typing.Type[C]) annotiert ist, Werte akzeptieren, die selbst Klassen sind – insbesondere akzeptiert sie das Klassenobjekt von C. Zum Beispiel

a = 3         # Has type ``int``
b = int       # Has type ``type[int]``
c = type(a)   # Also has type ``type[int]``

Beachten Sie, dass type[C] kovariant ist.

class User: ...
class ProUser(User): ...
class TeamUser(User): ...

def make_new_user(user_class: type[User]) -> User:
    # ...
    return user_class()

make_new_user(User)      # OK
make_new_user(ProUser)   # Also OK: ``type[ProUser]`` is a subtype of ``type[User]``
make_new_user(TeamUser)  # Still fine
make_new_user(User())    # Error: expected ``type[User]`` but got ``User``
make_new_user(int)       # Error: ``type[int]`` is not a subtype of ``type[User]``

Die einzig legalen Parameter für type sind Klassen, Any, Typ-Variablen und Vereinigungen aus diesen Typen. Zum Beispiel

def new_non_team_user(user_class: type[BasicUser | ProUser]): ...

new_non_team_user(BasicUser)  # OK
new_non_team_user(ProUser)    # OK
new_non_team_user(TeamUser)   # Error: ``type[TeamUser]`` is not a subtype
                              # of ``type[BasicUser | ProUser]``
new_non_team_user(User)       # Also an error

type[Any] ist äquivalent zu type, der Wurzel der Python-Hierarchie für Metaklassen.

Annotation von Generatoren und Coroutinen

Ein Generator kann mit dem generischen Typ Generator[YieldType, SendType, ReturnType] annotiert werden. Zum Beispiel

def echo_round() -> Generator[int, float, str]:
    sent = yield 0
    while sent >= 0:
        sent = yield round(sent)
    return 'Done'

Beachten Sie, dass der SendType von Generator, im Gegensatz zu vielen anderen generischen Klassen in der Standardbibliothek, kontravariant und nicht kovariant oder invariant ist.

Die Parameter SendType und ReturnType haben standardmäßig den Wert None.

def infinite_stream(start: int) -> Generator[int]:
    while True:
        yield start
        start += 1

Es ist auch möglich, diese Typen explizit festzulegen.

def infinite_stream(start: int) -> Generator[int, None, None]:
    while True:
        yield start
        start += 1

Einfache Generatoren, die nur Werte erzeugen, können auch so annotiert werden, dass sie einen Rückgabetyp von entweder Iterable[YieldType] oder Iterator[YieldType] haben.

def infinite_stream(start: int) -> Iterator[int]:
    while True:
        yield start
        start += 1

Asynchrone Generatoren werden auf ähnliche Weise behandelt, erwarten aber keinen ReturnType-Typargument (AsyncGenerator[YieldType, SendType]). Das Argument SendType hat standardmäßig den Wert None, sodass die folgenden Definitionen äquivalent sind.

async def infinite_stream(start: int) -> AsyncGenerator[int]:
    while True:
        yield start
        start = await increment(start)

async def infinite_stream(start: int) -> AsyncGenerator[int, None]:
    while True:
        yield start
        start = await increment(start)

Wie im synchronen Fall sind auch AsyncIterable[YieldType] und AsyncIterator[YieldType] verfügbar.

async def infinite_stream(start: int) -> AsyncIterator[int]:
    while True:
        yield start
        start = await increment(start)

Coroutinen können mit Coroutine[YieldType, SendType, ReturnType] annotiert werden. Die generischen Argumente entsprechen denen von Generator, zum Beispiel.

from collections.abc import Coroutine
c: Coroutine[list[str], str, int]  # Some coroutine defined elsewhere
x = c.send('hi')                   # Inferred type of 'x' is list[str]
async def bar() -> None:
    y = await c                    # Inferred type of 'y' is int

Benutzerdefinierte generische Typen

Eine benutzerdefinierte Klasse kann als generische Klasse definiert werden.

from logging import Logger

class LoggedVar[T]:
    def __init__(self, value: T, name: str, logger: Logger) -> None:
        self.name = name
        self.logger = logger
        self.value = value

    def set(self, new: T) -> None:
        self.log('Set ' + repr(self.value))
        self.value = new

    def get(self) -> T:
        self.log('Get ' + repr(self.value))
        return self.value

    def log(self, message: str) -> None:
        self.logger.info('%s: %s', self.name, message)

Diese Syntax zeigt an, dass die Klasse LoggedVar um eine einzelne Typ-Variable T parametrisiert ist. Dies macht T auch als Typ innerhalb des Klassenkörpers gültig.

Generische Klassen erben implizit von Generic. Für die Kompatibilität mit Python 3.11 und niedriger ist es auch möglich, explizit von Generic zu erben, um eine generische Klasse anzugeben.

from typing import TypeVar, Generic

T = TypeVar('T')

class LoggedVar(Generic[T]):
    ...

Generische Klassen haben Methoden __class_getitem__(), was bedeutet, dass sie zur Laufzeit parametrisiert werden können (z. B. LoggedVar[int] unten).

from collections.abc import Iterable

def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
    for var in vars:
        var.set(0)

Ein generischer Typ kann beliebig viele Typvariablen haben. Alle Arten von TypeVar sind als Parameter für einen generischen Typ zulässig.

from typing import TypeVar, Generic, Sequence

class WeirdTrio[T, B: Sequence[bytes], S: (int, str)]:
    ...

OldT = TypeVar('OldT', contravariant=True)
OldB = TypeVar('OldB', bound=Sequence[bytes], covariant=True)
OldS = TypeVar('OldS', int, str)

class OldWeirdTrio(Generic[OldT, OldB, OldS]):
    ...

Jede Typvariablen-Argument für Generic muss unterschiedlich sein. Dies ist daher ungültig.

from typing import TypeVar, Generic
...

class Pair[M, M]:  # SyntaxError
    ...

T = TypeVar('T')

class Pair(Generic[T, T]):   # INVALID
    ...

Generische Klassen können auch von anderen Klassen erben.

from collections.abc import Sized

class LinkedList[T](Sized):
    ...

Beim Erben von generischen Klassen können einige Typ-Parameter festgelegt werden.

from collections.abc import Mapping

class MyDict[T](Mapping[str, T]):
    ...

In diesem Fall hat MyDict einen einzelnen Parameter, T.

Die Verwendung einer generischen Klasse ohne Angabe von Typ-Parametern geht davon aus, dass für jede Position Any verwendet wird. Im folgenden Beispiel ist MyIterable nicht generisch, erbt aber implizit von Iterable[Any].

from collections.abc import Iterable

class MyIterable(Iterable): # Same as Iterable[Any]
    ...

Benutzerdefinierte generische Typ-Aliase werden ebenfalls unterstützt. Beispiele.

from collections.abc import Iterable

type Response[S] = Iterable[S] | int

# Return type here is same as Iterable[str] | int
def response(query: str) -> Response[str]:
    ...

type Vec[T] = Iterable[tuple[T, T]]

def inproduct[T: (int, float, complex)](v: Vec[T]) -> T: # Same as Iterable[tuple[T, T]]
    return sum(x*y for x, y in v)

Aus Kompatibilitätsgründen können generische Typ-Aliase auch durch eine einfache Zuweisung erstellt werden.

from collections.abc import Iterable
from typing import TypeVar

S = TypeVar("S")
Response = Iterable[S] | int

Geändert in Version 3.7: Generic hat keine benutzerdefinierte Metaklasse mehr.

Geändert in Version 3.12: Syntaktische Unterstützung für Generics und Typ-Aliase ist neu in Version 3.12. Zuvor mussten generische Klassen explizit von Generic erben oder eine Typ-Variable in einer ihrer Basisklassen enthalten.

Benutzerdefinierte Generics für Parameterausdrücke werden ebenfalls über Parameterspezifikationsvariablen in der Form [**P] unterstützt. Das Verhalten ist konsistent mit den oben beschriebenen Typvariablen, da Parameterspezifikationsvariablen vom Modul typing als spezialisierte Typvariable behandelt werden. Die einzige Ausnahme ist, dass eine Liste von Typen verwendet werden kann, um ein ParamSpec zu ersetzen.

>>> class Z[T, **P]: ...  # T is a TypeVar; P is a ParamSpec
...
>>> Z[int, [dict, float]]
__main__.Z[int, [dict, float]]

Klassen, die über ein ParamSpec generisch sind, können auch durch explizite Vererbung von Generic erstellt werden. In diesem Fall wird ** nicht verwendet.

from typing import ParamSpec, Generic

P = ParamSpec('P')

class Z(Generic[P]):
    ...

Ein weiterer Unterschied zwischen TypeVar und ParamSpec ist, dass ein Generic mit nur einer Parameterspezifikationsvariablen Parameterlisten in den Formen X[[Type1, Type2, ...]] und auch X[Type1, Type2, ...] aus ästhetischen Gründen akzeptiert. Intern wird Letzteres in das Erstere umgewandelt, sodass die folgenden Ausdrücke äquivalent sind.

>>> class X[**P]: ...
...
>>> X[int, str]
__main__.X[[int, str]]
>>> X[[int, str]]
__main__.X[[int, str]]

Beachten Sie, dass Generics mit ParamSpec in einigen Fällen möglicherweise keine korrekten __parameters__ nach der Ersetzung haben, da sie hauptsächlich für die statische Typüberprüfung gedacht sind.

Geändert in Version 3.10: Generic kann jetzt über Parameterausdrücke parametrisiert werden. Weitere Details finden Sie in ParamSpec und PEP 612.

Eine benutzerdefinierte generische Klasse kann ABCs als Basisklassen ohne Metaklassenkonflikt haben. Generische Metaklassen werden nicht unterstützt. Das Ergebnis der Parametrisierung von Generics wird zwischengespeichert, und die meisten Typen im Modul typing sind hashable und auf Gleichheit vergleichbar.

Der Typ Any

Eine spezielle Art von Typ ist Any. Ein statischer Typüberprüfer behandelt jeden Typ als kompatibel mit Any und Any als kompatibel mit jedem Typ.

Das bedeutet, dass es möglich ist, jede Operation oder jeden Methodenaufruf auf einem Wert vom Typ Any durchzuführen und ihn einer beliebigen Variablen zuzuweisen.

from typing import Any

a: Any = None
a = []          # OK
a = 2           # OK

s: str = ''
s = a           # OK

def foo(item: Any) -> int:
    # Passes type checking; 'item' could be any type,
    # and that type might have a 'bar' method
    item.bar()
    ...

Beachten Sie, dass keine Typüberprüfung durchgeführt wird, wenn ein Wert vom Typ Any einem präziseren Typ zugewiesen wird. Zum Beispiel hat der statische Typüberprüfer keinen Fehler gemeldet, als a s zugewiesen wurde, obwohl s als Typ str deklariert war und zur Laufzeit einen Wert vom Typ int erhält!

Darüber hinaus werden alle Funktionen ohne Rückgabetyp oder Parametertypen standardmäßig auf Any gesetzt.

def legacy_parser(text):
    ...
    return data

# A static type checker will treat the above
# as having the same signature as:
def legacy_parser(text: Any) -> Any:
    ...
    return data

Dieses Verhalten ermöglicht es Any als Notausgang zu verwenden, wenn Sie dynamisch und statisch typisierten Code mischen müssen.

Vergleichen Sie das Verhalten von Any mit dem von object. Ähnlich wie Any ist jeder Typ eine Unterklasse von object. Im Gegensatz zu Any ist das Umgekehrte jedoch nicht der Fall: object ist keine Unterklasse jedes anderen Typs.

Das bedeutet, wenn der Typ eines Wertes object ist, lehnt ein Typüberprüfer fast alle Operationen darauf ab, und die Zuweisung an eine Variable (oder die Verwendung als Rückgabewert) eines spezialisierteren Typs ist ein Typfehler. Zum Beispiel.

def hash_a(item: object) -> int:
    # Fails type checking; an object does not have a 'magic' method.
    item.magic()
    ...

def hash_b(item: Any) -> int:
    # Passes type checking
    item.magic()
    ...

# Passes type checking, since ints and strs are subclasses of object
hash_a(42)
hash_a("foo")

# Passes type checking, since Any is compatible with all types
hash_b(42)
hash_b("foo")

Verwenden Sie object, um anzugeben, dass ein Wert auf typsichere Weise jeder Typ sein könnte. Verwenden Sie Any, um anzugeben, dass ein Wert dynamisch typisiert ist.

Nominale vs. strukturelle Subtyps

Ursprünglich definierte PEP 484 das statische Python-Typsystem als Verwendung von nominalem Subtyping. Das bedeutet, dass eine Klasse A dort zulässig ist, wo eine Klasse B erwartet wird, wenn und nur wenn A eine Unterklasse von B ist.

Diese Anforderung galt zuvor auch für abstrakte Basisklassen, wie z. B. Iterable. Das Problem bei diesem Ansatz war, dass eine Klasse explizit markiert werden musste, um sie zu unterstützen, was unpythonisch ist und nicht dem entspricht, was man normalerweise im idiomatischen dynamisch typisierten Python-Code tun würde. Zum Beispiel entspricht dies PEP 484.

from collections.abc import Sized, Iterable, Iterator

class Bucket(Sized, Iterable[int]):
    ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[int]: ...

PEP 544 löst dieses Problem, indem es Benutzern ermöglicht, den obigen Code ohne explizite Basisklassen in der Klassendefinition zu schreiben, sodass Bucket von statischen Typüberprüfern implizit sowohl als Untertyp von Sized als auch von Iterable[int] betrachtet wird. Dies wird als strukturelles Subtyping (oder statisches Duck-Typing) bezeichnet.

from collections.abc import Iterator, Iterable

class Bucket:  # Note: no base classes
    ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[int]: ...

def collect(items: Iterable[int]) -> int: ...
result = collect(Bucket())  # Passes type check

Darüber hinaus kann ein Benutzer durch Unterklassifizierung einer speziellen Klasse Protocol neue benutzerdefinierte Protokolle definieren, um das strukturelle Subtyping vollständig zu nutzen (siehe Beispiele unten).

Modulinhalt

Das Modul typing definiert die folgenden Klassen, Funktionen und Dekoratoren.

Spezielle Typenprimitive

Spezielle Typen

Diese können als Typen in Annotationen verwendet werden. Sie unterstützen kein Abonnement mit [].

typing.Any

Spezieller Typ, der einen unbeschränkten Typ angibt.

  • Jeder Typ ist mit Any kompatibel.

  • Any ist mit jedem Typ kompatibel.

Geändert in Version 3.11: Any kann jetzt als Basisklasse verwendet werden. Dies kann nützlich sein, um Typenprüfungsfehler bei Klassen zu vermeiden, die überall Duck-Typing unterstützen oder sehr dynamisch sind.

typing.AnyStr

Eine beschränkte Tyavariable.

Definition

AnyStr = TypeVar('AnyStr', str, bytes)

AnyStr ist für Funktionen gedacht, die str oder bytes Argumente akzeptieren können, aber die beiden nicht mischen dürfen.

Zum Beispiel

def concat(a: AnyStr, b: AnyStr) -> AnyStr:
    return a + b

concat("foo", "bar")    # OK, output has type 'str'
concat(b"foo", b"bar")  # OK, output has type 'bytes'
concat("foo", b"bar")   # Error, cannot mix str and bytes

Beachten Sie, dass AnyStr trotz seines Namens nichts mit dem Any Typ zu tun hat, noch bedeutet es „beliebige Zeichenkette“. Insbesondere sind AnyStr und str | bytes unterschiedlich und haben unterschiedliche Anwendungsfälle.

# Invalid use of AnyStr:
# The type variable is used only once in the function signature,
# so cannot be "solved" by the type checker
def greet_bad(cond: bool) -> AnyStr:
    return "hi there!" if cond else b"greetings!"

# The better way of annotating this function:
def greet_proper(cond: bool) -> str | bytes:
    return "hi there!" if cond else b"greetings!"

Veraltet seit Version 3.13, wird in Version 3.18 entfernt: Veraltet zugunsten der neuen Typparametersyntax. Verwenden Sie class A[T: (str, bytes)]: ... anstelle des Imports von AnyStr. Weitere Details finden Sie in PEP 695.

In Python 3.16 wird AnyStr aus typing.__all__ entfernt, und Laufzeit-Deprecation-Warnungen werden ausgegeben, wenn darauf zugegriffen oder es aus typing importiert wird. AnyStr wird aus typing in Python 3.18 entfernt.

typing.LiteralString

Spezieller Typ, der nur literale Zeichenketten enthält.

Jede Zeichenkettenliterale ist mit LiteralString kompatibel, ebenso wie eine andere LiteralString. Ein als nur str typisiertes Objekt ist dies jedoch nicht. Eine durch die Zusammensetzung von LiteralString typisierten Objekten erstellte Zeichenkette ist ebenfalls als LiteralString zulässig.

Beispiel

def run_query(sql: LiteralString) -> None:
    ...

def caller(arbitrary_string: str, literal_string: LiteralString) -> None:
    run_query("SELECT * FROM students")  # OK
    run_query(literal_string)  # OK
    run_query("SELECT * FROM " + literal_string)  # OK
    run_query(arbitrary_string)  # type checker error
    run_query(  # type checker error
        f"SELECT * FROM students WHERE name = {arbitrary_string}"
    )

LiteralString ist nützlich für sensible APIs, bei denen willkürlich vom Benutzer generierte Zeichenketten Probleme verursachen könnten. Die beiden oben genannten Fälle, die Typenprüfungsfehler erzeugen, könnten beispielsweise anfällig für einen SQL-Injection-Angriff sein.

Weitere Details finden Sie in PEP 675.

Hinzugefügt in Version 3.11.

typing.Never
typing.NoReturn

Never und NoReturn repräsentieren den bottom type, einen Typ, der keine Elemente hat.

Sie können verwendet werden, um anzuzeigen, dass eine Funktion nie zurückkehrt, wie z. B. sys.exit()

from typing import Never  # or NoReturn

def stop() -> Never:
    raise RuntimeError('no way')

Oder um eine Funktion zu definieren, die niemals aufgerufen werden sollte, da es keine gültigen Argumente gibt, wie z. B. assert_never()

from typing import Never  # or NoReturn

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

def int_or_str(arg: int | str) -> None:
    never_call_me(arg)  # type checker error
    match arg:
        case int():
            print("It's an int")
        case str():
            print("It's a str")
        case _:
            never_call_me(arg)  # OK, arg is of type Never (or NoReturn)

Never und NoReturn haben die gleiche Bedeutung im Typsystem und statische Typenprüfer behandeln beide gleichwertig.

Hinzugefügt in Version 3.6.2: NoReturn hinzugefügt.

Hinzugefügt in Version 3.11: Never hinzugefügt.

typing.Self

Spezieller Typ zur Darstellung der aktuell umschließenden Klasse.

Zum Beispiel

from typing import Self, reveal_type

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

class SubclassOfFoo(Foo): pass

reveal_type(Foo().return_self())  # Revealed type is "Foo"
reveal_type(SubclassOfFoo().return_self())  # Revealed type is "SubclassOfFoo"

Diese Annotation ist semantisch äquivalent zu folgendem, wenn auch auf prägnantere Weise

from typing import TypeVar

Self = TypeVar("Self", bound="Foo")

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

Im Allgemeinen sollten Sie, wenn etwas self zurückgibt, wie in den obigen Beispielen, Self als Rückgabeannotation verwenden. Wenn Foo.return_self als Rückgabe von "Foo" annotiert wäre, würde der Typenprüfer das von SubclassOfFoo.return_self zurückgegebene Objekt als vom Typ Foo und nicht als SubclassOfFoo ableiten.

Weitere gängige Anwendungsfälle sind

  • classmethods, die als alternative Konstruktoren verwendet werden und Instanzen des cls-Parameters zurückgeben.

  • Annotation einer __enter__()-Methode, die self zurückgibt.

Sie sollten Self nicht als Rückgabeannotation verwenden, wenn die Methode nicht garantiert eine Instanz einer Unterklasse zurückgibt, wenn die Klasse unterklassenbildet wird.

class Eggs:
    # Self would be an incorrect return annotation here,
    # as the object returned is always an instance of Eggs,
    # even in subclasses
    def returns_eggs(self) -> "Eggs":
        return Eggs()

Weitere Details finden Sie in PEP 673.

Hinzugefügt in Version 3.11.

typing.TypeAlias

Spezielle Annotation zur expliziten Deklaration eines Typen-Alias.

Zum Beispiel

from typing import TypeAlias

Factors: TypeAlias = list[int]

TypeAlias ist besonders nützlich in älteren Python-Versionen zur Annotation von Aliasen, die Vorwärtsreferenzen verwenden, da es für Typenprüfer schwierig sein kann, diese von normalen Variablendeklarationen zu unterscheiden.

from typing import Generic, TypeAlias, TypeVar

T = TypeVar("T")

# "Box" does not exist yet,
# so we have to use quotes for the forward reference on Python <3.12.
# Using ``TypeAlias`` tells the type checker that this is a type alias declaration,
# not a variable assignment to a string.
BoxOfStrings: TypeAlias = "Box[str]"

class Box(Generic[T]):
    @classmethod
    def make_box_of_strings(cls) -> BoxOfStrings: ...

Weitere Details finden Sie in PEP 613.

Hinzugefügt in Version 3.10.

Veraltet seit Version 3.12: TypeAlias ist zugunsten der type-Anweisung veraltet, die Instanzen von TypeAliasType erstellt und die nativ Vorwärtsreferenzen unterstützt. Beachten Sie, dass TypeAlias und TypeAliasType zwar ähnliche Zwecke erfüllen und ähnliche Namen haben, aber unterschiedlich sind und letzteres nicht der Typ des ersteren ist. Eine Entfernung von TypeAlias ist derzeit nicht geplant, aber Benutzer werden ermutigt, auf type-Anweisungen umzusteigen.

Spezielle Formen

Diese können als Typen in Annotationen verwendet werden. Sie unterstützen alle die Subskription mit [], haben aber jeweils eine eindeutige Syntax.

class typing.Union

Vereinigungstyp; Union[X, Y] ist äquivalent zu X | Y und bedeutet entweder X oder Y.

Um eine Vereinigung zu definieren, verwenden Sie z. B. Union[int, str] oder die Kurzform int | str. Die Verwendung dieser Kurzform wird empfohlen. Details

  • Die Argumente müssen Typen sein und es muss mindestens ein Argument geben.

  • Vereinigungen von Vereinigungen werden abgeflacht, z. B.

    Union[Union[int, str], float] == Union[int, str, float]
    

    Dies gilt jedoch nicht für Vereinigungen, auf die über einen Typen-Alias verwiesen wird, um die Auswertung des zugrunde liegenden TypeAliasType zu vermeiden.

    type A = Union[int, str]
    Union[A, float] != Union[int, str, float]
    
  • Vereinigungen mit einem einzigen Argument verschwinden, z. B.

    Union[int] == int  # The constructor actually returns int
    
  • Redundante Argumente werden übersprungen, z. B.

    Union[int, str, int] == Union[int, str] == int | str
    
  • Beim Vergleichen von Vereinigungen wird die Argumentreihenfolge ignoriert, z. B.

    Union[int, str] == Union[str, int]
    
  • Sie können eine Union nicht unterklassen oder instanziieren.

  • Sie können nicht Union[X][Y] schreiben.

Geändert in Version 3.7: Explizite Unterklassen werden zur Laufzeit nicht mehr aus Vereinigungen entfernt.

Geändert in Version 3.10: Vereinigungen können jetzt als X | Y geschrieben werden. Siehe Vereinigungstyp-Ausdrücke.

Geändert in Version 3.14: types.UnionType ist jetzt ein Alias für Union, und sowohl Union[int, str] als auch int | str erstellen Instanzen derselben Klasse. Um zu prüfen, ob ein Objekt eine Union zur Laufzeit ist, verwenden Sie isinstance(obj, Union). Für Kompatibilität mit früheren Python-Versionen verwenden Sie get_origin(obj) is typing.Union or get_origin(obj) is types.UnionType.

typing.Optional

Optional[X] ist äquivalent zu X | None (oder Union[X, None]).

Beachten Sie, dass dies nicht dasselbe Konzept ist wie ein optionales Argument, das ein solches mit einem Standardwert ist. Ein optionales Argument mit einem Standardwert benötigt nicht unbedingt den Optional-Qualifizierer für seine Typannotation, nur weil es optional ist. Zum Beispiel

def foo(arg: int = 0) -> None:
    ...

Andererseits, wenn ein expliziter Wert von None erlaubt ist, ist die Verwendung von Optional angemessen, unabhängig davon, ob das Argument optional ist oder nicht. Zum Beispiel

def foo(arg: Optional[int] = None) -> None:
    ...

Geändert in Version 3.10: Optional kann jetzt als X | None geschrieben werden. Siehe Vereinigungstyp-Ausdrücke.

typing.Concatenate

Spezielle Form zur Annotation von höherrangigen Funktionen.

Concatenate kann in Verbindung mit Callable und ParamSpec verwendet werden, um einen höherrangigen aufrufbaren Typ zu annotieren, der Parameter eines anderen aufrufbaren Typs hinzufügt, entfernt oder transformiert. Die Verwendung erfolgt in der Form Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]. Concatenate ist derzeit nur gültig, wenn es als erstes Argument von Callable verwendet wird. Der letzte Parameter von Concatenate muss ein ParamSpec oder Ellipse (...) sein.

Um beispielsweise einen Dekorator with_lock zu annotieren, der eine threading.Lock für die dekorierte Funktion bereitstellt, kann Concatenate verwendet werden, um anzuzeigen, dass with_lock einen aufrufbaren Typ erwartet, der eine Lock als erstes Argument nimmt und einen aufrufbaren Typ mit einer anderen Signatur zurückgibt. In diesem Fall gibt ParamSpec an, dass die Parametertypen des zurückgegebenen aufrufbaren Typs von den Parametertypen des übergebenen aufrufbaren Typs abhängen.

from collections.abc import Callable
from threading import Lock
from typing import Concatenate

# Use this lock to ensure that only one thread is executing a function
# at any time.
my_lock = Lock()

def with_lock[**P, R](f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]:
    '''A type-safe decorator which provides a lock.'''
    def inner(*args: P.args, **kwargs: P.kwargs) -> R:
        # Provide the lock as the first argument.
        return f(my_lock, *args, **kwargs)
    return inner

@with_lock
def sum_threadsafe(lock: Lock, numbers: list[float]) -> float:
    '''Add a list of numbers together in a thread-safe manner.'''
    with lock:
        return sum(numbers)

# We don't need to pass in the lock ourselves thanks to the decorator.
sum_threadsafe([1.1, 2.2, 3.3])

Hinzugefügt in Version 3.10.

Siehe auch

typing.Literal

Spezielle Typsignatur zur Definition von „literalen Typen“.

Literal kann verwendet werden, um Typenprüfern anzuzeigen, dass das annotierte Objekt einen Wert hat, der einem der bereitgestellten Literale entspricht.

Zum Beispiel

def validate_simple(data: Any) -> Literal[True]:  # always returns True
    ...

type Mode = Literal['r', 'rb', 'w', 'wb']
def open_helper(file: str, mode: Mode) -> str:
    ...

open_helper('/some/path', 'r')      # Passes type check
open_helper('/other/path', 'typo')  # Error in type checker

Literal[...] kann nicht unterklassen werden. Zur Laufzeit ist jeder beliebige Wert als Typargument für Literal[...] zulässig, Typenprüfer können jedoch Einschränkungen auferlegen. Weitere Details zu literalen Typen finden Sie in PEP 586.

Zusätzliche Details

  • Die Argumente müssen literale Werte sein und es muss mindestens eines geben.

  • Verschachtelte Literal-Typen werden abgeflacht, z. B.

    assert Literal[Literal[1, 2], 3] == Literal[1, 2, 3]
    

    Dies gilt jedoch nicht für Literal-Typen, auf die über einen Typen-Alias verwiesen wird, um die Auswertung des zugrunde liegenden TypeAliasType zu vermeiden.

    type A = Literal[1, 2]
    assert Literal[A, 3] != Literal[1, 2, 3]
    
  • Redundante Argumente werden übersprungen, z. B.

    assert Literal[1, 2, 1] == Literal[1, 2]
    
  • Beim Vergleichen von Literalen wird die Argumentreihenfolge ignoriert, z. B.

    assert Literal[1, 2] == Literal[2, 1]
    
  • Sie können eine Literal nicht unterklassen oder instanziieren.

  • Sie können nicht Literal[X][Y] schreiben.

Hinzugefügt in Version 3.8.

Geändert in Version 3.9.1: Literal dedupliziert jetzt Parameter. Gleichheitsvergleiche von Literal-Objekten sind nicht mehr von der Reihenfolge abhängig. Literal-Objekte lösen bei Gleichheitsvergleichen eine TypeError-Ausnahme aus, wenn einer ihrer Parameter nicht hashbar ist.

typing.ClassVar

Spezielle Typkonstruktion zur Markierung von Klassenvariablen.

Wie in PEP 526 eingeführt, kennzeichnet eine Variablenannotation, die in ClassVar verpackt ist, dass ein bestimmtes Attribut als Klassenvariable verwendet werden soll und nicht auf Instanzen dieser Klasse gesetzt werden sollte. Verwendung

class Starship:
    stats: ClassVar[dict[str, int]] = {} # class variable
    damage: int = 10                     # instance variable

ClassVar akzeptiert nur Typen und kann nicht weiter abonniert werden.

ClassVar ist selbst keine Klasse und sollte nicht mit isinstance() oder issubclass() verwendet werden. ClassVar ändert das Laufzeitverhalten von Python nicht, kann aber von Drittanbieter-Typenprüfern verwendet werden. Zum Beispiel könnte ein Typenprüfer den folgenden Code als Fehler kennzeichnen.

enterprise_d = Starship(3000)
enterprise_d.stats = {} # Error, setting class variable on instance
Starship.stats = {}     # This is OK

Hinzugefügt in Version 3.5.3.

Geändert in Version 3.13: ClassVar kann jetzt in Final und umgekehrt verschachtelt werden.

typing.Final

Spezielle Typsignatur zur Kennzeichnung finaler Namen für Typenprüfer.

Finale Namen können in keinem Gültigkeitsbereich neu zugewiesen werden. In Klassenbereichen deklarierte finale Namen können in Unterklassen nicht überschrieben werden.

Zum Beispiel

MAX_SIZE: Final = 9000
MAX_SIZE += 1  # Error reported by type checker

class Connection:
    TIMEOUT: Final[int] = 10

class FastConnector(Connection):
    TIMEOUT = 1  # Error reported by type checker

Es gibt keine Laufzeitüberprüfung dieser Eigenschaften. Weitere Details finden Sie in PEP 591.

Hinzugefügt in Version 3.8.

Geändert in Version 3.13: Final kann jetzt in ClassVar und umgekehrt verschachtelt werden.

typing.Required

Spezielle Typsignatur zum Markieren eines Schlüssels in einem TypedDict als erforderlich.

Dies ist hauptsächlich nützlich für total=False TypedDicts. Weitere Details finden Sie in TypedDict und PEP 655.

Hinzugefügt in Version 3.11.

typing.NotRequired

Spezielle Typsignatur zum Markieren eines Schlüssels in einem TypedDict als potenziell fehlend.

Weitere Details finden Sie in TypedDict und PEP 655.

Hinzugefügt in Version 3.11.

typing.ReadOnly

Eine spezielle Typsignatur zum Markieren eines Elements eines TypedDict als schreibgeschützt.

Zum Beispiel

class Movie(TypedDict):
   title: ReadOnly[str]
   year: int

def mutate_movie(m: Movie) -> None:
   m["year"] = 1999  # allowed
   m["title"] = "The Matrix"  # typechecker error

Es gibt keine Laufzeitüberprüfung für diese Eigenschaft.

Weitere Details finden Sie in TypedDict und PEP 705.

Hinzugefügt in Version 3.13.

typing.Annotated

Spezielle Typsignatur zur Hinzufügung von kontextspezifischen Metadaten zu einer Annotation.

Fügen Sie einer gegebenen Typisierung T Metadaten x hinzu, indem Sie die Annotation Annotated[T, x] verwenden. Mit Annotated hinzugefügte Metadaten können von statischen Analysewerkzeugen oder zur Laufzeit verwendet werden. Zur Laufzeit werden die Metadaten in einem Attribut __metadata__ gespeichert.

Wenn eine Bibliothek oder ein Werkzeug eine Annotation Annotated[T, x] antrifft und keine spezielle Logik für die Metadaten hat, sollte es die Metadaten ignorieren und die Annotation einfach als T behandeln. Als solches kann Annotated für Code nützlich sein, der Annotationen für Zwecke außerhalb des statischen Typsystems von Python verwenden möchte.

Die Verwendung von Annotated[T, x] als Annotation ermöglicht weiterhin die statische Typenprüfung von T, da Typenprüfer die Metadaten x einfach ignorieren. Auf diese Weise unterscheidet sich Annotated vom @no_type_check-Dekorator, der auch zur Hinzufügung von Annotationen außerhalb des Umfangs des Typsystems verwendet werden kann, aber die Typenprüfung für eine Funktion oder Klasse vollständig deaktiviert.

Die Verantwortung für die Interpretation der Metadaten liegt bei dem Werkzeug oder der Bibliothek, die eine Annotated-Annotation vorfindet. Ein Werkzeug oder eine Bibliothek, die einen Annotated-Typ antrifft, kann die Metadatenelemente durchsuchen, um festzustellen, ob sie von Interesse sind (z. B. mithilfe von isinstance()).

Annotated[<Typ>, <Metadaten>]

Hier ist ein Beispiel dafür, wie Sie Annotated verwenden könnten, um Metadaten zu Typannotationen hinzuzufügen, wenn Sie eine Bereichsanalyse durchführen würden.

@dataclass
class ValueRange:
    lo: int
    hi: int

T1 = Annotated[int, ValueRange(-10, 5)]
T2 = Annotated[T1, ValueRange(-20, 3)]

Das erste Argument für Annotated muss ein gültiger Typ sein. Mehrere Metadatenelemente können angegeben werden, da Annotated variable Argumente unterstützt. Die Reihenfolge der Metadatenelemente bleibt erhalten und ist für Gleichheitsprüfungen wichtig.

@dataclass
class ctype:
     kind: str

a1 = Annotated[int, ValueRange(3, 10), ctype("char")]
a2 = Annotated[int, ctype("char"), ValueRange(3, 10)]

assert a1 != a2  # Order matters

Es liegt am Werkzeug, das die Annotationen konsumiert, zu entscheiden, ob der Client mehrere Metadatenelemente zu einer Annotation hinzufügen darf und wie diese Annotationen zusammengeführt werden.

Verschachtelte Annotated-Typen werden abgeflacht. Die Reihenfolge der Metadatenelemente beginnt mit der innersten Annotation.

assert Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[
    int, ValueRange(3, 10), ctype("char")
]

Dies gilt jedoch nicht für Annotated-Typen, auf die über einen Typen-Alias verwiesen wird, um die Auswertung des zugrunde liegenden TypeAliasType zu vermeiden.

type From3To10[T] = Annotated[T, ValueRange(3, 10)]
assert Annotated[From3To10[int], ctype("char")] != Annotated[
   int, ValueRange(3, 10), ctype("char")
]

Duplizierte Metadatenelemente werden nicht entfernt.

assert Annotated[int, ValueRange(3, 10)] != Annotated[
    int, ValueRange(3, 10), ValueRange(3, 10)
]

Annotated kann mit verschachtelten und generischen Aliasen verwendet werden.

@dataclass
class MaxLen:
    value: int

type Vec[T] = Annotated[list[tuple[T, T]], MaxLen(10)]

# When used in a type annotation, a type checker will treat "V" the same as
# ``Annotated[list[tuple[int, int]], MaxLen(10)]``:
type V = Vec[int]

Annotated kann nicht mit einem entpackten TypeVarTuple verwendet werden.

type Variadic[*Ts] = Annotated[*Ts, Ann1] = Annotated[T1, T2, T3, ..., Ann1]  # NOT valid

wobei T1, T2, ... TypeVars sind. Dies ist ungültig, da nur ein Typ an Annotated übergeben werden sollte.

Standardmäßig entfernt get_type_hints() die Metadaten aus Annotationen. Übergeben Sie include_extras=True, um die Metadaten beizubehalten.

>>> from typing import Annotated, get_type_hints
>>> def func(x: Annotated[int, "metadata"]) -> None: pass
...
>>> get_type_hints(func)
{'x': <class 'int'>, 'return': <class 'NoneType'>}
>>> get_type_hints(func, include_extras=True)
{'x': typing.Annotated[int, 'metadata'], 'return': <class 'NoneType'>}

Zur Laufzeit können die Metadaten, die einem Annotated-Typ zugeordnet sind, über das Attribut __metadata__ abgerufen werden.

>>> from typing import Annotated
>>> X = Annotated[int, "very", "important", "metadata"]
>>> X
typing.Annotated[int, 'very', 'important', 'metadata']
>>> X.__metadata__
('very', 'important', 'metadata')

Wenn Sie den ursprünglichen Typ abrufen möchten, der von Annotated umschlossen wird, verwenden Sie das Attribut __origin__.

>>> from typing import Annotated, get_origin
>>> Password = Annotated[str, "secret"]
>>> Password.__origin__
<class 'str'>

Beachten Sie, dass die Verwendung von get_origin() Annotated selbst zurückgibt.

>>> get_origin(Password)
typing.Annotated

Siehe auch

PEP 593 – Flexible Funktions- und Variablenannotationen

Die PEP, die Annotated in die Standardbibliothek eingeführt hat.

Hinzugefügt in Version 3.9.

typing.TypeIs

Spezielle Typsignatur zum Markieren benutzerdefinierter Typprädikatfunktionen.

TypeIs kann verwendet werden, um den Rückgabetyp einer benutzerdefinierten Typprädikatfunktion zu annotieren. TypeIs akzeptiert nur ein einzelnes Typargument. Zur Laufzeit sollten Funktionen, die auf diese Weise markiert sind, einen booleschen Wert zurückgeben und mindestens ein Positionsargument akzeptieren.

TypeIs zielt darauf ab, *Typ-Narrowing* zu unterstützen – eine Technik, die von statischen Typenprüfern verwendet wird, um einen präziseren Typ eines Ausdrucks innerhalb des Programmablaufs zu ermitteln. Normalerweise wird Typ-Narrowing durch die Analyse des bedingten Programmablaufs und die Anwendung des Narrowings auf einen Codeblock durchgeführt. Der bedingte Ausdruck wird hier manchmal als „Typprädikat“ bezeichnet.

def is_str(val: str | float):
    # "isinstance" type predicate
    if isinstance(val, str):
        # Type of ``val`` is narrowed to ``str``
        ...
    else:
        # Else, type of ``val`` is narrowed to ``float``.
        ...

Manchmal ist es praktisch, eine benutzerdefinierte boolesche Funktion als Typprädikat zu verwenden. Eine solche Funktion sollte TypeIs[...] oder TypeGuard als Rückgabetyp verwenden, um statische Typenprüfer auf diese Absicht aufmerksam zu machen. TypeIs hat normalerweise ein intuitiveres Verhalten als TypeGuard, kann aber nicht verwendet werden, wenn die Eingabe- und Ausgabetypen inkompatibel sind (z. B. list[object] zu list[int]) oder wenn die Funktion nicht True für alle Instanzen des verengten Typs zurückgibt.

Die Verwendung von -> TypeIs[NarrowedType] teilt dem statischen Typenprüfer mit, dass für eine gegebene Funktion

  1. Der Rückgabewert ist ein boolescher Wert.

  2. Wenn der Rückgabewert True ist, ist der Typ seines Arguments die Schnittmenge des ursprünglichen Typs des Arguments und NarrowedType.

  3. Wenn der Rückgabewert False ist, wird der Typ seines Arguments auf den Ausschluss von NarrowedType verengt.

Zum Beispiel

from typing import assert_type, final, TypeIs

class Parent: pass
class Child(Parent): pass
@final
class Unrelated: pass

def is_parent(val: object) -> TypeIs[Parent]:
    return isinstance(val, Parent)

def run(arg: Child | Unrelated):
    if is_parent(arg):
        # Type of ``arg`` is narrowed to the intersection
        # of ``Parent`` and ``Child``, which is equivalent to
        # ``Child``.
        assert_type(arg, Child)
    else:
        # Type of ``arg`` is narrowed to exclude ``Parent``,
        # so only ``Unrelated`` is left.
        assert_type(arg, Unrelated)

Der Typ innerhalb von TypeIs muss mit dem Typ des Funktionsarguments übereinstimmen; falls dies nicht der Fall ist, lösen statische Typenprüfer einen Fehler aus. Eine falsch geschriebene TypeIs-Funktion kann zu inkonsistentem Verhalten im Typsystem führen; es liegt in der Verantwortung des Benutzers, solche Funktionen typsicher zu schreiben.

Wenn eine TypeIs-Funktion eine Klassen- oder Instanzmethode ist, dann bezieht sich der Typ in TypeIs auf den Typ des zweiten Parameters (nach cls oder self).

Kurz gesagt, die Form def foo(arg: TypeA) -> TypeIs[TypeB]: ... bedeutet, dass, wenn foo(arg) True zurückgibt, arg eine Instanz von TypeB ist, und wenn es False zurückgibt, ist es keine Instanz von TypeB.

TypeIs funktioniert auch mit Tyvariablen. Weitere Informationen finden Sie in PEP 742 (Narrowing types with TypeIs).

Hinzugefügt in Version 3.13.

typing.TypeGuard

Spezielle Typsignatur zum Markieren benutzerdefinierter Typprädikatfunktionen.

Typ-Prädikatfunktionen sind benutzerdefinierte Funktionen, die zurückgeben, ob ihr Argument eine Instanz eines bestimmten Typs ist. TypeGuard funktioniert ähnlich wie TypeIs, hat aber subtil andere Auswirkungen auf das Verhalten der Typüberprüfung (siehe unten).

Die Verwendung von -> TypeGuard teilt dem statischen Typenprüfer mit, dass für eine gegebene Funktion

  1. Der Rückgabewert ist ein boolescher Wert.

  2. Wenn der Rückgabewert True ist, hat der Typ seines Arguments den Typ innerhalb von TypeGuard.

TypeGuard funktioniert auch mit Tyvariablen. Weitere Details finden Sie in PEP 647.

Zum Beispiel

def is_str_list(val: list[object]) -> TypeGuard[list[str]]:
    '''Determines whether all objects in the list are strings'''
    return all(isinstance(x, str) for x in val)

def func1(val: list[object]):
    if is_str_list(val):
        # Type of ``val`` is narrowed to ``list[str]``.
        print(" ".join(val))
    else:
        # Type of ``val`` remains as ``list[object]``.
        print("Not a list of strings!")

TypeIs und TypeGuard unterscheiden sich in folgenden Punkten:

  • TypeIs verlangt, dass der verengte Typ eine Unterart des Eingabetyps ist, während TypeGuard dies nicht tut. Der Hauptgrund dafür ist, dass Dinge wie das Verengen von list[object] zu list[str] ermöglicht werden, obwohl letzteres keine Unterart ersteren ist, da list invariant ist.

  • Wenn eine TypeGuard-Funktion True zurückgibt, verengen Typenprüfer den Typ der Variablen auf exakt den TypeGuard-Typ. Wenn eine TypeIs-Funktion True zurückgibt, können Typenprüfer einen präziseren Typ ableiten, indem sie den zuvor bekannten Typ der Variablen mit dem TypeIs-Typ kombinieren. (Technisch gesehen wird dies als Schnittmengentyp bezeichnet.)

  • Wenn eine TypeGuard-Funktion False zurückgibt, können Typenprüfer den Typ der Variablen überhaupt nicht verengen. Wenn eine TypeIs-Funktion False zurückgibt, können Typenprüfer den Typ der Variablen verengen, um den TypeIs-Typ auszuschließen.

Hinzugefügt in Version 3.10.

typing.Unpack

Typing-Operator, um ein Objekt konzeptionell als "entpackt" zu markieren.

Zum Beispiel ist die Verwendung des Entpackungsoperators * auf ein Typtupel äquivalent zur Verwendung von Unpack, um das Typtupel als entpackt zu markieren.

Ts = TypeVarTuple('Ts')
tup: tuple[*Ts]
# Effectively does:
tup: tuple[Unpack[Ts]]

Tatsächlich kann Unpack im Kontext von typing.TypeVarTuple und builtins.tuple-Typen austauschbar mit * verwendet werden. Möglicherweise sehen Sie Unpack explizit in älteren Python-Versionen verwendet, wo * an bestimmten Stellen nicht verwendet werden konnte.

# In older versions of Python, TypeVarTuple and Unpack
# are located in the `typing_extensions` backports package.
from typing_extensions import TypeVarTuple, Unpack

Ts = TypeVarTuple('Ts')
tup: tuple[*Ts]         # Syntax error on Python <= 3.10!
tup: tuple[Unpack[Ts]]  # Semantically equivalent, and backwards-compatible

Unpack kann auch zusammen mit typing.TypedDict verwendet werden, um **kwargs in einer Funktionssignatur zu typisieren.

from typing import TypedDict, Unpack

class Movie(TypedDict):
    name: str
    year: int

# This function expects two keyword arguments - `name` of type `str`
# and `year` of type `int`.
def foo(**kwargs: Unpack[Movie]): ...

Weitere Details zur Verwendung von Unpack für die Typisierung von **kwargs finden Sie in PEP 692.

Hinzugefügt in Version 3.11.

Erstellung von generischen Typen und Typ-Aliassen

Die folgenden Klassen sollten nicht direkt als Annotationen verwendet werden. Ihr beabsichtigter Zweck ist es, Bausteine für die Erstellung von generischen Typen und Typ-Aliassen zu sein.

Diese Objekte können über spezielle Syntax (Typparameterlisten und die type-Anweisung) erstellt werden. Zur Kompatibilität mit Python 3.11 und früher können sie auch ohne die dedizierte Syntax erstellt werden, wie unten dokumentiert.

class typing.Generic

Abstrakte Basisklasse für generische Typen.

Ein generischer Typ wird typischerweise durch Hinzufügen einer Liste von Typparametern nach dem Klassennamen deklariert.

class Mapping[KT, VT]:
    def __getitem__(self, key: KT) -> VT:
        ...
        # Etc.

Eine solche Klasse erbt implizit von Generic. Die Laufzeitsemantik dieser Syntax wird in der Sprachreferenz diskutiert.

Diese Klasse kann dann wie folgt verwendet werden:

def lookup_name[X, Y](mapping: Mapping[X, Y], key: X, default: Y) -> Y:
    try:
        return mapping[key]
    except KeyError:
        return default

Hier geben die Klammern nach dem Funktionsnamen eine generische Funktion an.

Aus Gründen der Abwärtskompatibilität können generische Klassen auch durch explizites Erben von Generic deklariert werden. In diesem Fall müssen die Typparameter separat deklariert werden:

KT = TypeVar('KT')
VT = TypeVar('VT')

class Mapping(Generic[KT, VT]):
    def __getitem__(self, key: KT) -> VT:
        ...
        # Etc.
class typing.TypeVar(name, *constraints, bound=None, covariant=False, contravariant=False, infer_variance=False, default=typing.NoDefault)

Typparameter.

Der bevorzugte Weg zur Erstellung eines Typparameters ist über die dedizierte Syntax für generische Funktionen, generische Klassen und generische Typ-Aliasse.

class Sequence[T]:  # T is a TypeVar
    ...

Diese Syntax kann auch verwendet werden, um gebundene und eingeschränkte Typparameter zu erstellen:

class StrSequence[S: str]:  # S is a TypeVar with a `str` upper bound;
    ...                     # we can say that S is "bounded by `str`"


class StrOrBytesSequence[A: (str, bytes)]:  # A is a TypeVar constrained to str or bytes
    ...

Wenn gewünscht, können wiederverwendbare Typparameter jedoch auch manuell konstruiert werden, wie folgt:

T = TypeVar('T')  # Can be anything
S = TypeVar('S', bound=str)  # Can be any subtype of str
A = TypeVar('A', str, bytes)  # Must be exactly str or bytes

Typparameter existieren primär zum Nutzen statischer Typenprüfer. Sie dienen als Parameter für generische Typen sowie für Definitionen von generischen Funktionen und Typ-Aliassen. Weitere Informationen zu generischen Typen finden Sie unter Generic. Generische Funktionen funktionieren wie folgt:

def repeat[T](x: T, n: int) -> Sequence[T]:
    """Return a list containing n references to x."""
    return [x]*n


def print_capitalized[S: str](x: S) -> S:
    """Print x capitalized, and return x."""
    print(x.capitalize())
    return x


def concatenate[A: (str, bytes)](x: A, y: A) -> A:
    """Add two strings or bytes objects together."""
    return x + y

Beachten Sie, dass Typparameter *gebunden*, *eingeschränkt* oder weder noch sein können, aber nicht sowohl gebunden als auch eingeschränkt.

Die Varianz von Typparametern wird von Typenprüfern abgeleitet, wenn sie über die Typparametersyntax erstellt werden oder wenn infer_variance=True übergeben wird. Manuell erstellte Typparameter können explizit als kovariant oder kontravariant markiert werden, indem covariant=True oder contravariant=True übergeben wird. Standardmäßig sind manuell erstellte Typparameter invariant. Weitere Informationen finden Sie in PEP 484 und PEP 695.

Gebundene Typparameter und eingeschränkte Typparameter haben in mehreren wichtigen Punkten unterschiedliche Semantiken. Die Verwendung eines *gebundenen* Typparameters bedeutet, dass der TypeVar mit dem höchstmöglichen Typ gelöst wird.

x = print_capitalized('a string')
reveal_type(x)  # revealed type is str

class StringSubclass(str):
    pass

y = print_capitalized(StringSubclass('another string'))
reveal_type(y)  # revealed type is StringSubclass

z = print_capitalized(45)  # error: int is not a subtype of str

Die Obergrenze eines Typparameters kann ein konkreter Typ, ein abstrakter Typ (ABC oder Protokoll) oder sogar eine Vereinigung von Typen sein.

# Can be anything with an __abs__ method
def print_abs[T: SupportsAbs](arg: T) -> None:
    print("Absolute value:", abs(arg))

U = TypeVar('U', bound=str|bytes)  # Can be any subtype of the union str|bytes
V = TypeVar('V', bound=SupportsAbs)  # Can be anything with an __abs__ method

Die Verwendung eines *eingeschränkten* Typparameters bedeutet jedoch, dass der TypeVar immer nur als exakt einer der angegebenen Einschränkungen gelöst werden kann.

a = concatenate('one', 'two')
reveal_type(a)  # revealed type is str

b = concatenate(StringSubclass('one'), StringSubclass('two'))
reveal_type(b)  # revealed type is str, despite StringSubclass being passed in

c = concatenate('one', b'two')  # error: type variable 'A' can be either str or bytes in a function call, but not both

Zur Laufzeit löst isinstance(x, T) eine TypeError aus.

__name__

Der Name des Typparameters.

__covariant__

Ob der Typparameter explizit als kovariant markiert wurde.

__contravariant__

Ob der Typparameter explizit als kontravariant markiert wurde.

__infer_variance__

Ob die Varianz des Typparameters von Typenprüfern abgeleitet werden soll.

Hinzugefügt in Version 3.12.

__bound__

Die Obergrenze des Typparameters, falls vorhanden.

Geändert in Version 3.12: Für Typparameter, die über die Typparametersyntax erstellt wurden, wird die Obergrenze erst ausgewertet, wenn auf das Attribut zugegriffen wird, nicht wenn der Typparameter erstellt wird (siehe Lazy Evaluation).

evaluate_bound()

Eine Auswertungsfunktion, die dem Attribut __bound__ entspricht. Wenn sie direkt aufgerufen wird, unterstützt diese Methode nur das Format VALUE, was dem direkten Zugriff auf das Attribut __bound__ entspricht. Das Methodenobjekt kann jedoch an annotationlib.call_evaluate_function() übergeben werden, um den Wert in einem anderen Format auszuwerten.

Hinzugefügt in Version 3.14.

__constraints__

Ein Tupel, das die Einschränkungen des Typparameters, falls vorhanden, enthält.

Geändert in Version 3.12: Für Typparameter, die über die Typparametersyntax erstellt wurden, werden die Einschränkungen erst ausgewertet, wenn auf das Attribut zugegriffen wird, nicht wenn der Typparameter erstellt wird (siehe Lazy Evaluation).

evaluate_constraints()

Eine Auswertungsfunktion, die dem Attribut __constraints__ entspricht. Wenn sie direkt aufgerufen wird, unterstützt diese Methode nur das Format VALUE, was dem direkten Zugriff auf das Attribut __constraints__ entspricht. Das Methodenobjekt kann jedoch an annotationlib.call_evaluate_function() übergeben werden, um den Wert in einem anderen Format auszuwerten.

Hinzugefügt in Version 3.14.

__default__

Der Standardwert des Typparameters oder typing.NoDefault, wenn kein Standardwert vorhanden ist.

Hinzugefügt in Version 3.13.

evaluate_default()

Eine Auswertungsfunktion, die dem Attribut __default__ entspricht. Wenn sie direkt aufgerufen wird, unterstützt diese Methode nur das Format VALUE, was dem direkten Zugriff auf das Attribut __default__ entspricht. Das Methodenobjekt kann jedoch an annotationlib.call_evaluate_function() übergeben werden, um den Wert in einem anderen Format auszuwerten.

Hinzugefügt in Version 3.14.

has_default()

Gibt zurück, ob der Typparameter einen Standardwert hat. Dies ist äquivalent zur Prüfung, ob __default__ nicht die typing.NoDefault-Singleton ist, außer dass die Auswertung des lazy ausgewerteten Standardwerts nicht erzwungen wird.

Hinzugefügt in Version 3.13.

Geändert in Version 3.12: Typparameter können nun über die durch PEP 695 eingeführte Typparameter-Syntax deklariert werden. Der Parameter infer_variance wurde hinzugefügt.

Geändert in Version 3.13: Unterstützung für Standardwerte wurde hinzugefügt.

class typing.TypeVarTuple(name, *, default=typing.NoDefault)

Typparametertupel. Eine spezialisierte Form von Typparameter, die *variadische* Generika ermöglicht.

Typparametertupel können in Typparameterlisten mit einem einzelnen Sternchen (*) vor dem Namen deklariert werden.

def move_first_element_to_last[T, *Ts](tup: tuple[T, *Ts]) -> tuple[*Ts, T]:
    return (*tup[1:], tup[0])

Oder durch explizites Aufrufen des TypeVarTuple-Konstruktors:

T = TypeVar("T")
Ts = TypeVarTuple("Ts")

def move_first_element_to_last(tup: tuple[T, *Ts]) -> tuple[*Ts, T]:
    return (*tup[1:], tup[0])

Ein normales Typparameter ermöglicht die Parametrisierung mit einem einzelnen Typ. Ein Typparametertupel hingegen erlaubt die Parametrisierung mit einer *beliebigen* Anzahl von Typen, indem es wie eine *beliebige* Anzahl von in einem Tupel verpackten Typparametern funktioniert. Zum Beispiel:

# T is bound to int, Ts is bound to ()
# Return value is (1,), which has type tuple[int]
move_first_element_to_last(tup=(1,))

# T is bound to int, Ts is bound to (str,)
# Return value is ('spam', 1), which has type tuple[str, int]
move_first_element_to_last(tup=(1, 'spam'))

# T is bound to int, Ts is bound to (str, float)
# Return value is ('spam', 3.0, 1), which has type tuple[str, float, int]
move_first_element_to_last(tup=(1, 'spam', 3.0))

# This fails to type check (and fails at runtime)
# because tuple[()] is not compatible with tuple[T, *Ts]
# (at least one element is required)
move_first_element_to_last(tup=())

Beachten Sie die Verwendung des Entpackungsoperators * in tuple[T, *Ts]. Konzeptionell können Sie sich Ts als ein Tupel von Typparametern (T1, T2, ...) vorstellen. tuple[T, *Ts] würde dann zu tuple[T, *(T1, T2, ...)] werden, was äquivalent zu tuple[T, T1, T2, ...] ist. (Beachten Sie, dass Sie in älteren Python-Versionen dies möglicherweise stattdessen mit Unpack geschrieben sehen, z. B. Unpack[Ts].)

Typparametertupel müssen *immer* entpackt werden. Dies hilft, Typparametertupel von normalen Typparametern zu unterscheiden.

x: Ts          # Not valid
x: tuple[Ts]   # Not valid
x: tuple[*Ts]  # The correct way to do it

Typparametertupel können in denselben Kontexten wie normale Typparameter verwendet werden. Zum Beispiel in Klassendefinitionen, Argumenten und Rückgabetypen:

class Array[*Shape]:
    def __getitem__(self, key: tuple[*Shape]) -> float: ...
    def __abs__(self) -> "Array[*Shape]": ...
    def get_shape(self) -> tuple[*Shape]: ...

Typparametertupel können problemlos mit normalen Typparametern kombiniert werden:

class Array[DType, *Shape]:  # This is fine
    pass

class Array2[*Shape, DType]:  # This would also be fine
    pass

class Height: ...
class Width: ...

float_array_1d: Array[float, Height] = Array()     # Totally fine
int_array_2d: Array[int, Height, Width] = Array()  # Yup, fine too

Beachten Sie jedoch, dass höchstens ein Typparametertupel in einer einzelnen Liste von Typargumenten oder Typparametern erscheinen darf.

x: tuple[*Ts, *Ts]            # Not valid
class Array[*Shape, *Shape]:  # Not valid
    pass

Schließlich kann ein entpacktes Typparametertupel als Typannotation für *args verwendet werden:

def call_soon[*Ts](
    callback: Callable[[*Ts], None],
    *args: *Ts
) -> None:
    ...
    callback(*args)

Im Gegensatz zu nicht entpackten Annotationen von *args - z. B. *args: int, was besagen würde, dass *alle* Argumente int sind - ermöglicht *args: *Ts die Referenzierung der Typen der *einzelnen* Argumente in *args. Hier können wir dadurch sicherstellen, dass die Typen der an call_soon übergebenen *args mit den Typen der (positionalen) Argumente von callback übereinstimmen.

Weitere Details zu Typparametertupeln finden Sie in PEP 646.

__name__

Der Name des Typparametertupels.

__default__

Der Standardwert des Typparametertupels oder typing.NoDefault, wenn kein Standardwert vorhanden ist.

Hinzugefügt in Version 3.13.

evaluate_default()

Eine Auswertungsfunktion, die dem Attribut __default__ entspricht. Wenn sie direkt aufgerufen wird, unterstützt diese Methode nur das Format VALUE, was dem direkten Zugriff auf das Attribut __default__ entspricht. Das Methodenobjekt kann jedoch an annotationlib.call_evaluate_function() übergeben werden, um den Wert in einem anderen Format auszuwerten.

Hinzugefügt in Version 3.14.

has_default()

Gibt zurück, ob das Typparametertupel einen Standardwert hat. Dies ist äquivalent zur Prüfung, ob __default__ nicht die typing.NoDefault-Singleton ist, außer dass die Auswertung des lazy ausgewerteten Standardwerts nicht erzwungen wird.

Hinzugefügt in Version 3.13.

Hinzugefügt in Version 3.11.

Geändert in Version 3.12: Typparametertupel können nun über die durch PEP 695 eingeführte Typparameter-Syntax deklariert werden.

Geändert in Version 3.13: Unterstützung für Standardwerte wurde hinzugefügt.

class typing.ParamSpec(name, *, bound=None, covariant=False, contravariant=False, default=typing.NoDefault)

Parameter-Spezifikationsvariable. Eine spezialisierte Version von Typparametern.

In Typparameterlisten können Parameter-Spezifikationen mit zwei Sternchen (**) deklariert werden:

type IntFunc[**P] = Callable[P, int]

Zur Kompatibilität mit Python 3.11 und früher können ParamSpec-Objekte auch wie folgt erstellt werden:

P = ParamSpec('P')

Parameter-Spezifikationsvariablen existieren primär zum Nutzen statischer Typenprüfer. Sie werden verwendet, um die Parametertypen eines Callables an ein anderes Callable weiterzuleiten - ein Muster, das häufig in höherwertigen Funktionen und Decorators vorkommt. Sie sind nur gültig, wenn sie in Concatenate oder als erstes Argument für Callable verwendet werden, oder als Parameter für benutzerdefinierte Generika. Weitere Informationen zu generischen Typen finden Sie unter Generic.

Um beispielsweise grundlegende Protokollierung zu einer Funktion hinzuzufügen, kann ein Decorator add_logging erstellt werden, um Funktionsaufrufe zu protokollieren. Die Parameter-Spezifikationsvariable teilt dem Typenprüfer mit, dass das an den Decorator übergebene Callable und das daraus zurückgegebene neue Callable voneinander abhängige Typparameter haben:

from collections.abc import Callable
import logging

def add_logging[T, **P](f: Callable[P, T]) -> Callable[P, T]:
    '''A type-safe decorator to add logging to a function.'''
    def inner(*args: P.args, **kwargs: P.kwargs) -> T:
        logging.info(f'{f.__name__} was called')
        return f(*args, **kwargs)
    return inner

@add_logging
def add_two(x: float, y: float) -> float:
    '''Add two numbers together.'''
    return x + y

Ohne ParamSpec war der einfachste Weg, dies zuvor zu annotieren, die Verwendung eines TypeVar mit der Obergrenze Callable[..., Any]. Dies verursacht jedoch zwei Probleme:

  1. Der Typenprüfer kann die inner-Funktion nicht typisieren, da *args und **kwargs als Any typisiert werden müssen.

  2. cast() kann im Körper des add_logging-Decorators erforderlich sein, wenn die inner-Funktion zurückgegeben wird, oder der statische Typenprüfer muss angewiesen werden, return inner zu ignorieren.

args
kwargs

Da ParamSpec sowohl positionelle als auch Schlüsselwortparameter erfasst, können P.args und P.kwargs verwendet werden, um ein ParamSpec in seine Komponenten zu zerlegen. P.args repräsentiert das Tupel der positionellen Parameter in einem gegebenen Aufruf und sollte nur zur Annotation von *args verwendet werden. P.kwargs repräsentiert die Abbildung von Schlüsselwortparametern auf ihre Werte in einem gegebenen Aufruf und sollte nur zur Annotation von **kwargs verwendet werden. Beide Attribute erfordern, dass der annotierte Parameter im Gültigkeitsbereich liegt. Zur Laufzeit sind P.args und P.kwargs Instanzen von ParamSpecArgs bzw. ParamSpecKwargs.

__name__

Der Name der Parameterspezifikation.

__default__

Der Standardwert der Parameterspezifikation oder typing.NoDefault, falls kein Standardwert vorhanden ist.

Hinzugefügt in Version 3.13.

evaluate_default()

Eine evaluate-Funktion, die dem Attribut __default__ entspricht. Wenn diese Methode direkt aufgerufen wird, unterstützt sie nur das Format VALUE, was dem direkten Zugriff auf das Attribut __default__ entspricht. Das Methodenobjekt kann jedoch an annotationlib.call_evaluate_function() übergeben werden, um den Wert in einem anderen Format zu evaluieren.

Hinzugefügt in Version 3.14.

has_default()

Gibt zurück, ob die Parameterspezifikation einen Standardwert hat. Dies entspricht der Prüfung, ob __default__ nicht das Singleton typing.NoDefault ist, außer dass dies nicht zur Auswertung des lazy ausgewerteten Standardwerts zwingt.

Hinzugefügt in Version 3.13.

Mit covariant=True oder contravariant=True erstellte Parameterspezifikationsvariablen können verwendet werden, um kovariante oder kontravariante generische Typen zu deklarieren. Das Argument bound wird ebenfalls akzeptiert, ähnlich wie bei TypeVar. Die genaue Semantik dieser Schlüsselwörter ist jedoch noch nicht festgelegt.

Hinzugefügt in Version 3.10.

Geändert in Version 3.12: Parameterspezifikationen können jetzt mit der durch PEP 695 eingeführten Typ-Parameter-Syntax deklariert werden.

Geändert in Version 3.13: Unterstützung für Standardwerte wurde hinzugefügt.

Hinweis

Nur im globalen Geltungsbereich definierte Parameterspezifikationsvariablen können gepickelt werden.

Siehe auch

typing.ParamSpecArgs
typing.ParamSpecKwargs

Argumente und Schlüsselwortargumentattribute einer ParamSpec. Das Attribut P.args einer ParamSpec ist eine Instanz von ParamSpecArgs, und P.kwargs ist eine Instanz von ParamSpecKwargs. Sie sind für die Laufzeitinspektion gedacht und haben keine spezielle Bedeutung für statische Typenprüfer.

Das Aufrufen von get_origin() für eines dieser Objekte gibt die ursprüngliche ParamSpec zurück

>>> from typing import ParamSpec, get_origin
>>> P = ParamSpec("P")
>>> get_origin(P.args) is P
True
>>> get_origin(P.kwargs) is P
True

Hinzugefügt in Version 3.10.

class typing.TypeAliasType(name, value, *, type_params=())

Der Typ von Typaliasen, die über die type-Anweisung erstellt wurden.

Beispiel

>>> type Alias = int
>>> type(Alias)
<class 'typing.TypeAliasType'>

Hinzugefügt in Version 3.12.

__name__

Der Name des Typalias

>>> type Alias = int
>>> Alias.__name__
'Alias'
__module__

Der Name des Moduls, in dem der Typalias definiert wurde

>>> type Alias = int
>>> Alias.__module__
'__main__'
__type_params__

Die Typ-Parameter des Typalias, oder ein leeres Tupel, wenn der Alias nicht generisch ist

>>> type ListOrSet[T] = list[T] | set[T]
>>> ListOrSet.__type_params__
(T,)
>>> type NotGeneric = int
>>> NotGeneric.__type_params__
()
__value__

Der Wert des Typalias. Dieser wird lazy ausgewertet, sodass Namen, die in der Definition des Alias verwendet werden, erst aufgelöst werden, wenn auf das Attribut __value__ zugegriffen wird.

>>> type Mutually = Recursive
>>> type Recursive = Mutually
>>> Mutually
Mutually
>>> Recursive
Recursive
>>> Mutually.__value__
Recursive
>>> Recursive.__value__
Mutually
evaluate_value()

Eine evaluate-Funktion, die dem Attribut __value__ entspricht. Wenn diese Methode direkt aufgerufen wird, unterstützt sie nur das Format VALUE, was dem direkten Zugriff auf das Attribut __value__ entspricht. Das Methodenobjekt kann jedoch an annotationlib.call_evaluate_function() übergeben werden, um den Wert in einem anderen Format zu evaluieren.

>>> type Alias = undefined
>>> Alias.__value__
Traceback (most recent call last):
...
NameError: name 'undefined' is not defined
>>> from annotationlib import Format, call_evaluate_function
>>> Alias.evaluate_value(Format.VALUE)
Traceback (most recent call last):
...
NameError: name 'undefined' is not defined
>>> call_evaluate_function(Alias.evaluate_value, Format.FORWARDREF)
ForwardRef('undefined')

Hinzugefügt in Version 3.14.

Entpacken

Typ-Aliase unterstützen das Stern-Entpacken mit der Syntax *Alias. Dies entspricht der direkten Verwendung von Unpack[Alias].

>>> type Alias = tuple[int, str]
>>> type Unpacked = tuple[bool, *Alias]
>>> Unpacked.__value__
tuple[bool, typing.Unpack[Alias]]

Hinzugefügt in Version 3.14.

Andere spezielle Direktiven

Diese Funktionen und Klassen sollten nicht direkt als Annotationen verwendet werden. Ihr beabsichtigter Zweck ist es, Bausteine für die Erstellung und Deklaration von Typen zu sein.

class typing.NamedTuple

Typ-isierte Version von collections.namedtuple().

Verwendung

class Employee(NamedTuple):
    name: str
    id: int

Dies ist äquivalent zu

Employee = collections.namedtuple('Employee', ['name', 'id'])

Um einem Feld einen Standardwert zu geben, können Sie es im Klassenkörper zuweisen.

class Employee(NamedTuple):
    name: str
    id: int = 3

employee = Employee('Guido')
assert employee.id == 3

Felder mit einem Standardwert müssen nach allen Feldern ohne Standardwert stehen.

Die resultierende Klasse hat ein zusätzliches Attribut __annotations__, das ein Wörterbuch enthält, das die Feldnamen den Feldtypen zuordnet. (Die Feldnamen befinden sich im Attribut _fields und die Standardwerte im Attribut _field_defaults, die beide Teil der namedtuple()-API sind.)

NamedTuple-Unterklassen können auch Docstrings und Methoden haben.

class Employee(NamedTuple):
    """Represents an employee."""
    name: str
    id: int = 3

    def __repr__(self) -> str:
        return f'<Employee {self.name}, id={self.id}>'

NamedTuple-Unterklassen können generisch sein.

class Group[T](NamedTuple):
    key: T
    group: list[T]

Abwärtskompatible Nutzung

# For creating a generic NamedTuple on Python 3.11
T = TypeVar("T")

class Group(NamedTuple, Generic[T]):
    key: T
    group: list[T]

# A functional syntax is also supported
Employee = NamedTuple('Employee', [('name', str), ('id', int)])

Geändert in Version 3.6: Unterstützung für die PEP 526 Variablensyntax für Annotationen hinzugefügt.

Geändert in Version 3.6.1: Unterstützung für Standardwerte, Methoden und Docstrings hinzugefügt.

Geändert in Version 3.8: Die Attribute _field_types und __annotations__ sind nun reguläre Wörterbücher anstelle von Instanzen von OrderedDict.

Geändert in Version 3.9: Das Attribut _field_types wurde zugunsten des standardmäßigeren Attributs __annotations__ entfernt, das dieselben Informationen enthält.

Geändert in Version 3.11: Unterstützung für generische Named-Tuples hinzugefügt.

Geändert in Version 3.14: Die Verwendung von super() (und der Closure-Variable __class__) in Methoden von NamedTuple-Unterklassen wird nicht unterstützt und verursacht einen TypeError.

Veraltet seit Version 3.13, wird entfernt in Version 3.15: Die undokumentierte Schlüsselwortargument-Syntax zum Erstellen von NamedTuple-Klassen (NT = NamedTuple("NT", x=int)) ist veraltet und wird in 3.15 nicht mehr erlaubt. Verwenden Sie stattdessen die klassenbasierte Syntax oder die funktionale Syntax.

Veraltet seit Version 3.13, wird entfernt in Version 3.15: Beim Verwenden der funktionalen Syntax zum Erstellen einer NamedTuple-Klasse ist das Nicht-Übergeben eines Werts an den Parameter 'fields' (NT = NamedTuple("NT")) veraltet. Das Übergeben von None an den Parameter 'fields' (NT = NamedTuple("NT", None)) ist ebenfalls veraltet. Beides wird in Python 3.15 nicht mehr erlaubt. Um eine NamedTuple-Klasse mit 0 Feldern zu erstellen, verwenden Sie class NT(NamedTuple): pass oder NT = NamedTuple("NT", []).

class typing.NewType(name, tp)

Hilfsklasse zur Erstellung von unterscheidbaren Typen mit geringem Overhead.

Ein NewType wird von einem Typenprüfer als eigenständiger Typ betrachtet. Zur Laufzeit gibt das Aufrufen eines NewType jedoch sein Argument unverändert zurück.

Verwendung

UserId = NewType('UserId', int)  # Declare the NewType "UserId"
first_user = UserId(1)  # "UserId" returns the argument unchanged at runtime
__module__

Der Name des Moduls, in dem der neue Typ definiert ist.

__name__

Der Name des neuen Typs.

__supertype__

Der Typ, auf dem der neue Typ basiert.

Hinzugefügt in Version 3.5.2.

Geändert in Version 3.10: NewType ist nun eine Klasse anstelle einer Funktion.

class typing.Protocol(Generic)

Basisklasse für Protokollklassen.

Protokollklassen werden wie folgt definiert

class Proto(Protocol):
    def meth(self) -> int:
        ...

Solche Klassen werden hauptsächlich mit statischen Typenprüfern verwendet, die strukturelle Untertypen (statisches Duck-Typing) erkennen, zum Beispiel

class C:
    def meth(self) -> int:
        return 0

def func(x: Proto) -> int:
    return x.meth()

func(C())  # Passes static type check

Weitere Details finden Sie in PEP 544. Protokollklassen, die mit runtime_checkable() (später beschrieben) dekoriert sind, verhalten sich wie einfache Laufzeitprotokolle, die nur die Anwesenheit gegebener Attribute prüfen und ihre Typensignaturen ignorieren. Protokollklassen ohne diesen Dekorator können nicht als zweites Argument für isinstance() oder issubclass() verwendet werden.

Protokollklassen können generisch sein, zum Beispiel

class GenProto[T](Protocol):
    def meth(self) -> T:
        ...

In Code, der mit Python 3.11 oder älter kompatibel sein muss, können generische Protokolle wie folgt geschrieben werden

T = TypeVar("T")

class GenProto(Protocol[T]):
    def meth(self) -> T:
        ...

Hinzugefügt in Version 3.8.

@typing.runtime_checkable

Markiert eine Protokollklasse als Laufzeitprotokoll.

Ein solches Protokoll kann mit isinstance() und issubclass() verwendet werden. Dies ermöglicht eine einfache strukturelle Überprüfung, ähnlich wie "one trick ponies" in collections.abc wie Iterable. Zum Beispiel

@runtime_checkable
class Closable(Protocol):
    def close(self): ...

assert isinstance(open('/some/file'), Closable)

@runtime_checkable
class Named(Protocol):
    name: str

import threading
assert isinstance(threading.Thread(name='Bob'), Named)

Dieser Dekorator löst einen TypeError aus, wenn er auf eine Nicht-Protokollklasse angewendet wird.

Hinweis

runtime_checkable() prüft nur die Anwesenheit der erforderlichen Methoden oder Attribute, nicht deren Typensignaturen oder Typen. Zum Beispiel ist ssl.SSLObject eine Klasse, daher besteht sie eine issubclass()-Prüfung gegen Callable. Die Methode ssl.SSLObject.__init__ existiert jedoch nur, um einen TypeError mit einer aussagekräftigeren Meldung auszulösen, wodurch das Aufrufen (Instanziieren) von ssl.SSLObject unmöglich wird.

Hinweis

Eine isinstance()-Prüfung gegen ein laufzeitfähiges Protokoll kann im Vergleich zu einer isinstance()-Prüfung gegen eine Nicht-Protokollklasse überraschend langsam sein. Ziehen Sie in Betracht, alternative Idiome wie hasattr()-Aufrufe für strukturelle Prüfungen in leistungskritischem Code zu verwenden.

Hinzugefügt in Version 3.8.

Geändert in Version 3.12: Die interne Implementierung von isinstance()-Prüfungen gegen laufzeitfähige Protokolle verwendet nun inspect.getattr_static() zum Nachschlagen von Attributen (zuvor wurde hasattr() verwendet). Infolgedessen werden einige Objekte, die zuvor als Instanzen eines laufzeitfähigen Protokolls galten, ab Python 3.12 möglicherweise nicht mehr als Instanzen dieses Protokolls betrachtet, und umgekehrt. Die meisten Benutzer werden von dieser Änderung wahrscheinlich nicht betroffen sein.

Geändert in Version 3.12: Die Mitglieder eines laufzeitfähigen Protokolls gelten nun zur Laufzeit als "eingefroren", sobald die Klasse erstellt wurde. Monkey-Patching von Attributen auf ein laufzeitfähiges Protokoll funktioniert weiterhin, hat aber keine Auswirkungen auf isinstance()-Prüfungen, die Objekte mit dem Protokoll vergleichen. Weitere Informationen finden Sie unter Was ist neu in Python 3.12.

class typing.TypedDict(dict)

Spezielle Konstruktion zur Hinzufügung von Typ-Hinweisen zu einem Wörterbuch. Zur Laufzeit ist es ein normales dict.

TypedDict deklariert einen Wörterbuchtyp, der erwartet, dass alle seine Instanzen eine bestimmte Menge von Schlüsseln haben, wobei jedem Schlüssel ein Wert eines konsistenten Typs zugeordnet ist. Diese Erwartung wird nicht zur Laufzeit überprüft, sondern nur von Typenprüfern erzwungen. Verwendung

class Point2D(TypedDict):
    x: int
    y: int
    label: str

a: Point2D = {'x': 1, 'y': 2, 'label': 'good'}  # OK
b: Point2D = {'z': 3, 'label': 'bad'}           # Fails type check

assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')

Eine alternative Methode zur Erstellung eines TypedDict ist die Verwendung der Funktionsaufruf-Syntax. Das zweite Argument muss ein literales dict sein.

Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})

Diese funktionale Syntax ermöglicht die Definition von Schlüsseln, die keine gültigen Bezeichner sind, zum Beispiel, weil sie Schlüsselwörter sind oder Bindestriche enthalten, oder wenn Schlüsselnamen nicht gemangelt werden sollen, wie reguläre private Namen.

# raises SyntaxError
class Point2D(TypedDict):
    in: int  # 'in' is a keyword
    x-y: int  # name with hyphens

class Definition(TypedDict):
    __schema: str  # mangled to `_Definition__schema`

# OK, functional syntax
Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})
Definition = TypedDict('Definition', {'__schema': str})  # not mangled

Standardmäßig müssen alle Schlüssel in einem TypedDict vorhanden sein. Es ist möglich, einzelne Schlüssel als nicht erforderlich zu markieren, indem NotRequired verwendet wird.

class Point2D(TypedDict):
    x: int
    y: int
    label: NotRequired[str]

# Alternative syntax
Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': NotRequired[str]})

Das bedeutet, dass ein Point2D TypedDict den Schlüssel label weglassen kann.

Es ist auch möglich, alle Schlüssel standardmäßig als nicht erforderlich zu markieren, indem eine Totalität von False angegeben wird.

class Point2D(TypedDict, total=False):
    x: int
    y: int

# Alternative syntax
Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False)

Das bedeutet, dass ein Point2D TypedDict einen beliebigen der Schlüssel weglassen kann. Es wird erwartet, dass ein Typenprüfer nur ein literales False oder True als Wert für das Argument total unterstützt. True ist der Standardwert und macht alle im Klassenkörper definierten Elemente erforderlich.

Einzelne Schlüssel eines total=False TypedDict können mit Required als erforderlich markiert werden.

class Point2D(TypedDict, total=False):
    x: Required[int]
    y: Required[int]
    label: str

# Alternative syntax
Point2D = TypedDict('Point2D', {
    'x': Required[int],
    'y': Required[int],
    'label': str
}, total=False)

Es ist möglich, dass ein TypedDict-Typ von einem oder mehreren anderen TypedDict-Typen unter Verwendung der klassenbasierten Syntax erbt. Verwendung

class Point3D(Point2D):
    z: int

Point3D hat drei Elemente: x, y und z. Dies entspricht dieser Definition

class Point3D(TypedDict):
    x: int
    y: int
    z: int

Ein TypedDict kann nicht von einer Nicht-TypedDict-Klasse erben, außer von Generic. Zum Beispiel

class X(TypedDict):
    x: int

class Y(TypedDict):
    y: int

class Z(object): pass  # A non-TypedDict class

class XY(X, Y): pass  # OK

class XZ(X, Z): pass  # raises TypeError

Ein TypedDict kann generisch sein.

class Group[T](TypedDict):
    key: T
    group: list[T]

Um ein generisches TypedDict zu erstellen, das mit Python 3.11 oder älter kompatibel ist, erben Sie explizit von Generic.

T = TypeVar("T")

class Group(TypedDict, Generic[T]):
    key: T
    group: list[T]

Ein TypedDict kann über Annotationswörterbücher (siehe Best Practices für Annotationen für weitere Informationen zu Best Practices für Annotationen), __total__, __required_keys__ und __optional_keys__ introspektiert werden.

__total__

Point2D.__total__ gibt den Wert des Arguments total zurück. Beispiel

>>> from typing import TypedDict
>>> class Point2D(TypedDict): pass
>>> Point2D.__total__
True
>>> class Point2D(TypedDict, total=False): pass
>>> Point2D.__total__
False
>>> class Point3D(Point2D): pass
>>> Point3D.__total__
True

Dieses Attribut spiegelt *nur* den Wert des Arguments total für die aktuelle TypedDict-Klasse wider, nicht ob die Klasse semantisch total ist. Zum Beispiel kann ein TypedDict mit __total__ auf True gesetzt haben Schlüssel, die mit NotRequired markiert sind, oder er kann von einem anderen TypedDict mit total=False erben. Daher ist es im Allgemeinen besser, __required_keys__ und __optional_keys__ für die Introspektion zu verwenden.

__required_keys__

Hinzugefügt in Version 3.9.

__optional_keys__

Point2D.__required_keys__ und Point2D.__optional_keys__ geben frozenset-Objekte zurück, die die erforderlichen und nicht erforderlichen Schlüssel enthalten, bzw. die nicht erforderlichen Schlüssel.

Mit Required markierte Schlüssel erscheinen immer in __required_keys__, und mit NotRequired markierte Schlüssel erscheinen immer in __optional_keys__.

Für Abwärtskompatibilität mit Python 3.10 und älter ist es auch möglich, Vererbung zu verwenden, um sowohl erforderliche als auch nicht erforderliche Schlüssel im selben TypedDict zu deklarieren. Dies geschieht, indem ein TypedDict mit einem Wert für das total-Argument deklariert und dann von einem anderen TypedDict mit einem anderen Wert für total abgeleitet wird.

>>> class Point2D(TypedDict, total=False):
...     x: int
...     y: int
...
>>> class Point3D(Point2D):
...     z: int
...
>>> Point3D.__required_keys__ == frozenset({'z'})
True
>>> Point3D.__optional_keys__ == frozenset({'x', 'y'})
True

Hinzugefügt in Version 3.9.

Hinweis

Wenn from __future__ import annotations verwendet wird oder wenn Annotationen als Zeichenketten gegeben sind, werden Annotationen nicht ausgewertet, wenn das TypedDict definiert wird. Daher funktionieren die Laufzeit-Introspektionen, auf denen __required_keys__ und __optional_keys__ basieren, möglicherweise nicht richtig, und die Werte der Attribute können falsch sein.

Die Unterstützung für ReadOnly spiegelt sich in den folgenden Attributen wider

__readonly_keys__

Ein frozenset, der die Namen aller schreibgeschützten Schlüssel enthält. Schlüssel sind schreibgeschützt, wenn sie den ReadOnly-Qualifizierer tragen.

Hinzugefügt in Version 3.13.

__mutable_keys__

Ein frozenset, der die Namen aller veränderlichen Schlüssel enthält. Schlüssel sind veränderlich, wenn sie den ReadOnly-Qualifizierer nicht tragen.

Hinzugefügt in Version 3.13.

Weitere Beispiele und detaillierte Regeln finden Sie im Abschnitt TypedDict in der Typdokumentation.

Hinzugefügt in Version 3.8.

Geändert in Version 3.11: Unterstützung für die Kennzeichnung einzelner Schlüssel als Required oder NotRequired hinzugefügt. Siehe PEP 655.

Geändert in Version 3.11: Unterstützung für generische TypedDicts hinzugefügt.

Geändert in Version 3.13: Unterstützung für die Keyword-Argument-Methode zur Erstellung von TypedDicts entfernt.

Geändert in Version 3.13: Unterstützung für den ReadOnly-Qualifizierer hinzugefügt.

Vom Vorgänger seit Version 3.13, wird in Version 3.15 entfernt: Bei Verwendung der funktionalen Syntax zum Erstellen einer TypedDict-Klasse ist es veraltet, dem Parameter 'fields' keinen Wert zu übergeben (TD = TypedDict("TD")). Die Übergabe von None an den 'fields'-Parameter (TD = TypedDict("TD", None)) ist ebenfalls veraltet. Beide werden in Python 3.15 nicht mehr zugelassen. Um eine TypedDict-Klasse mit 0 Feldern zu erstellen, verwenden Sie class TD(TypedDict): pass oder TD = TypedDict("TD", {}).

Protokolle

Die folgenden Protokolle werden vom Modul typing bereitgestellt. Alle sind mit @runtime_checkable dekoriert.

class typing.SupportsAbs

Eine ABC mit einer abstrakten Methode __abs__, die in ihrem Rückgabetyp kovariant ist.

class typing.SupportsBytes

Eine ABC mit einer abstrakten Methode __bytes__.

class typing.SupportsComplex

Eine ABC mit einer abstrakten Methode __complex__.

class typing.SupportsFloat

Eine ABC mit einer abstrakten Methode __float__.

class typing.SupportsIndex

Eine ABC mit einer abstrakten Methode __index__.

Hinzugefügt in Version 3.8.

class typing.SupportsInt

Eine ABC mit einer abstrakten Methode __int__.

class typing.SupportsRound

Eine ABC mit einer abstrakten Methode __round__, die in ihrem Rückgabetyp kovariant ist.

ABCs und Protokolle für die Arbeit mit I/O

class typing.IO[AnyStr]
class typing.TextIO[AnyStr]
class typing.BinaryIO[AnyStr]

Die generische Klasse IO[AnyStr] und ihre Unterklassen TextIO(IO[str]) und BinaryIO(IO[bytes]) repräsentieren die Typen von I/O-Streams wie die von open() zurückgegebenen. Bitte beachten Sie, dass diese Klassen keine Protokolle sind und ihre Schnittstelle recht breit gefasst ist.

Die Protokolle io.Reader und io.Writer bieten eine einfachere Alternative für Argumenttypen, wenn nur die Methoden read() oder write() zugegriffen werden, jeweils

def read_and_write(reader: Reader[str], writer: Writer[bytes]):
    data = reader.read()
    writer.write(data.encode())

Ziehen Sie auch die Verwendung von collections.abc.Iterable für die Iteration über die Zeilen eines Eingabestreams in Betracht

def read_config(stream: Iterable[str]):
    for line in stream:
        ...

Funktionen und Dekoratoren

typing.cast(typ, val)

Wirft einen Wert auf einen Typ.

Dies gibt den Wert unverändert zurück. Für den Typprüfer signalisiert dies, dass der Rückgabewert den angegebenen Typ hat, aber zur Laufzeit wird absichtlich nichts überprüft (wir wollen, dass dies so schnell wie möglich ist).

typing.assert_type(val, typ, /)

Fordert einen statischen Typprüfer auf, zu bestätigen, dass val den abgeleiteten Typ typ hat.

Zur Laufzeit tut dies nichts: Es gibt das erste Argument unverändert und ohne Prüfungen oder Nebeneffekte zurück, unabhängig vom tatsächlichen Typ des Arguments.

Wenn ein statischer Typprüfer auf einen Aufruf von assert_type() stößt, gibt er einen Fehler aus, wenn der Wert nicht vom angegebenen Typ ist.

def greet(name: str) -> None:
    assert_type(name, str)  # OK, inferred type of `name` is `str`
    assert_type(name, int)  # type checker error

Diese Funktion ist nützlich, um sicherzustellen, dass das Verständnis eines Skripts durch den Typprüfer mit den Absichten des Entwicklers übereinstimmt.

def complex_function(arg: object):
    # Do some complex type-narrowing logic,
    # after which we hope the inferred type will be `int`
    ...
    # Test whether the type checker correctly understands our function
    assert_type(arg, int)

Hinzugefügt in Version 3.11.

typing.assert_never(arg, /)

Fordert einen statischen Typprüfer auf, zu bestätigen, dass eine Codezeile nicht erreichbar ist.

Beispiel

def int_or_str(arg: int | str) -> None:
    match arg:
        case int():
            print("It's an int")
        case str():
            print("It's a str")
        case _ as unreachable:
            assert_never(unreachable)

Hier erlauben die Annotationen dem Typprüfer, abzuleiten, dass der letzte Fall niemals ausgeführt werden kann, da arg entweder ein int oder ein str ist und beide Optionen durch frühere Fälle abgedeckt sind.

Wenn ein Typprüfer feststellt, dass ein Aufruf von assert_never() erreichbar ist, gibt er einen Fehler aus. Wenn beispielsweise die Typannotation für arg stattdessen int | str | float wäre, würde der Typprüfer einen Fehler ausgeben, der darauf hinweist, dass unreachable vom Typ float ist. Damit ein Aufruf von assert_never die Typprüfung besteht, muss der abgeleitete Typ des übergebenen Arguments der unterste Typ, Never, sein und nichts anderes.

Zur Laufzeit löst dies eine Ausnahme aus, wenn es aufgerufen wird.

Siehe auch

Unerreichbarer Code und Vollständigkeitsprüfung enthält weitere Informationen zur Vollständigkeitsprüfung mit statischer Typisierung.

Hinzugefügt in Version 3.11.

typing.reveal_type(obj, /)

Fordert einen statischen Typprüfer auf, den abgeleiteten Typ eines Ausdrucks preiszugeben.

Wenn ein statischer Typprüfer auf einen Aufruf dieser Funktion stößt, gibt er eine Diagnose mit dem abgeleiteten Typ des Arguments aus. Zum Beispiel

x: int = 1
reveal_type(x)  # Revealed type is "builtins.int"

Dies kann nützlich sein, wenn Sie debuggen möchten, wie Ihr Typprüfer mit einem bestimmten Codeausschnitt umgeht.

Zur Laufzeit gibt diese Funktion den Laufzeittyp ihres Arguments an sys.stderr aus und gibt das Argument unverändert zurück (wodurch der Aufruf innerhalb eines Ausdrucks verwendet werden kann).

x = reveal_type(1)  # prints "Runtime type is int"
print(x)  # prints "1"

Beachten Sie, dass der Laufzeittyp vom Typ, der statisch von einem Typprüfer abgeleitet wurde, abweichen kann (weniger oder spezifischer).

Die meisten Typprüfer unterstützen reveal_type() überall, auch wenn der Name nicht von typing importiert wurde. Das Importieren des Namens von typing ermöglicht jedoch, dass Ihr Code ohne Laufzeitfehler ausgeführt wird und die Absicht klarer kommuniziert.

Hinzugefügt in Version 3.11.

@typing.dataclass_transform(*, eq_default=True, order_default=False, kw_only_default=False, frozen_default=False, field_specifiers=(), **kwargs)

Dekorator zur Kennzeichnung eines Objekts, das dataclass-ähnliches Verhalten aufweist.

dataclass_transform kann verwendet werden, um eine Klasse, eine Metaklasse oder eine Funktion zu dekorieren, die selbst ein Dekorator ist. Die Anwesenheit von @dataclass_transform() teilt einem statischen Typprüfer mit, dass das dekorierte Objekt zur Laufzeit "Magie" ausführt, die eine Klasse ähnlich wie @dataclasses.dataclass transformiert.

Beispiel für die Verwendung mit einer Dekoratorfunktion

@dataclass_transform()
def create_model[T](cls: type[T]) -> type[T]:
    ...
    return cls

@create_model
class CustomerModel:
    id: int
    name: str

Auf einer Basisklasse

@dataclass_transform()
class ModelBase: ...

class CustomerModel(ModelBase):
    id: int
    name: str

Auf einer Metaklasse

@dataclass_transform()
class ModelMeta(type): ...

class ModelBase(metaclass=ModelMeta): ...

class CustomerModel(ModelBase):
    id: int
    name: str

Die oben definierten CustomerModel-Klassen werden von Typprüfern ähnlich wie mit @dataclasses.dataclass erstellte Klassen behandelt. Zum Beispiel gehen Typprüfer davon aus, dass diese Klassen __init__-Methoden haben, die id und name akzeptieren.

Die dekorierten Klasse, Metaklasse oder Funktion können die folgenden booleschen Argumente akzeptieren, von denen Typprüfer annehmen, dass sie die gleiche Wirkung haben wie beim @dataclasses.dataclass-Dekorator: init, eq, order, unsafe_hash, frozen, match_args, kw_only und slots. Es muss möglich sein, den Wert dieser Argumente (True oder False) statisch auszuwerten.

Die Argumente des dataclass_transform-Dekorators können verwendet werden, um die Standardverhalten der dekorierten Klasse, Metaklasse oder Funktion anzupassen.

Parameter:
  • eq_default (bool) – Zeigt an, ob angenommen wird, dass der Parameter eq True oder False ist, wenn er vom Aufrufer weggelassen wird. Standardmäßig True.

  • order_default (bool) – Zeigt an, ob angenommen wird, dass der Parameter order True oder False ist, wenn er vom Aufrufer weggelassen wird. Standardmäßig False.

  • kw_only_default (bool) – Zeigt an, ob angenommen wird, dass der Parameter kw_only True oder False ist, wenn er vom Aufrufer weggelassen wird. Standardmäßig False.

  • frozen_default (bool) –

    Zeigt an, ob angenommen wird, dass der Parameter frozen True oder False ist, wenn er vom Aufrufer weggelassen wird. Standardmäßig False.

    Hinzugefügt in Version 3.12.

  • field_specifiers (tuple[Callable[..., Any], ...]) – Gibt eine statische Liste unterstützter Klassen oder Funktionen an, die Felder beschreiben, ähnlich wie dataclasses.field(). Standardmäßig ().

  • **kwargs (Any) – Beliebige andere Schlüsselwortargumente werden akzeptiert, um mögliche zukünftige Erweiterungen zu ermöglichen.

Typprüfer erkennen die folgenden optionalen Parameter bei Feldangaben

Erkannte Parameter für Feldangaben

Parametername

Beschreibung

init

Zeigt an, ob das Feld in die synthetisierte __init__-Methode aufgenommen werden soll. Wenn nicht angegeben, ist init standardmäßig True.

default

Gibt den Standardwert für das Feld an.

default_factory

Gibt eine Laufzeit-Callback-Funktion an, die den Standardwert für das Feld zurückgibt. Wenn weder default noch default_factory angegeben sind, wird angenommen, dass das Feld keinen Standardwert hat und bei der Instanziierung der Klasse ein Wert bereitgestellt werden muss.

factory

Ein Alias für den Parameter default_factory bei Feldangaben.

kw_only

Zeigt an, ob das Feld als nur mit Schlüsselwort zu übergebend gekennzeichnet werden soll. Wenn True, ist das Feld nur mit Schlüsselwort zu übergebend. Wenn False, ist es nicht nur mit Schlüsselwort zu übergebend. Wenn nicht angegeben, wird der Wert des Parameters kw_only des mit dataclass_transform dekorierten Objekts verwendet, oder wenn dieser nicht angegeben ist, der Wert von kw_only_default auf dataclass_transform verwendet.

alias

Gibt einen alternativen Namen für das Feld an. Dieser alternative Name wird in der synthetisierten __init__-Methode verwendet.

Zur Laufzeit zeichnet dieser Dekorator seine Argumente im Attribut __dataclass_transform__ des dekorierten Objekts auf. Er hat keine anderen Laufzeitwirkungen.

Weitere Details finden Sie in PEP 681.

Hinzugefügt in Version 3.11.

@typing.overload

Dekorator zum Erstellen überladener Funktionen und Methoden.

Der Dekorator @overload ermöglicht die Beschreibung von Funktionen und Methoden, die mehrere verschiedene Kombinationen von Argumenttypen unterstützen. Eine Reihe von mit @overload dekorierten Definitionen muss von genau einer nicht mit @overload dekorierten Definition (für dieselbe Funktion/Methode) gefolgt werden.

Mit @overload dekorierte Definitionen sind nur für den Typprüfer bestimmt, da sie von der nicht mit @overload dekorierten Definition überschrieben werden. Die nicht mit @overload dekorierte Definition wird hingegen zur Laufzeit verwendet, sollte aber von einem Typprüfer ignoriert werden. Zur Laufzeit löst der direkte Aufruf einer mit @overload dekorierten Funktion eine NotImplementedError aus.

Ein Beispiel für eine Überladung, die einen präziseren Typ liefert, als mit einer Union oder einem Typvariablen ausgedrückt werden kann

@overload
def process(response: None) -> None:
    ...
@overload
def process(response: int) -> tuple[int, str]:
    ...
@overload
def process(response: bytes) -> str:
    ...
def process(response):
    ...  # actual implementation goes here

Weitere Details und ein Vergleich mit anderen Typisierungssemantiken finden Sie in PEP 484.

Geändert in Version 3.11: Überladene Funktionen können jetzt zur Laufzeit mit get_overloads() introspektiert werden.

typing.get_overloads(func)

Gibt eine Sequenz von mit @overload dekorierten Definitionen für func zurück.

func ist das Funktions-Objekt für die Implementierung der überladenen Funktion. Gegeben die Definition von process in der Dokumentation von @overload, gibt get_overloads(process) eine Sequenz von drei Funktions-Objekten für die drei definierten Überladungen zurück. Wenn aufgerufen auf eine Funktion ohne Überladungen, gibt get_overloads() eine leere Sequenz zurück.

get_overloads() kann zur Introspektion einer überladenen Funktion zur Laufzeit verwendet werden.

Hinzugefügt in Version 3.11.

typing.clear_overloads()

Löscht alle registrierten Überladungen im internen Register.

Dies kann verwendet werden, um den vom Register verwendeten Speicher zurückzufordern.

Hinzugefügt in Version 3.11.

@typing.final

Dekorator zur Kennzeichnung von finalen Methoden und finalen Klassen.

Das Dekorieren einer Methode mit @final zeigt einem Typprüfer an, dass die Methode in einer Unterklasse nicht überschrieben werden kann. Das Dekorieren einer Klasse mit @final zeigt an, dass sie nicht unterklassifiziert werden kann.

Zum Beispiel

class Base:
    @final
    def done(self) -> None:
        ...
class Sub(Base):
    def done(self) -> None:  # Error reported by type checker
        ...

@final
class Leaf:
    ...
class Other(Leaf):  # Error reported by type checker
    ...

Es gibt keine Laufzeitüberprüfung dieser Eigenschaften. Weitere Einzelheiten finden Sie in PEP 591.

Hinzugefügt in Version 3.8.

Geändert in Version 3.11: Der Dekorator versucht nun, ein Attribut __final__ auf True des dekorierten Objekts zu setzen. Daher kann eine Überprüfung wie if getattr(obj, "__final__", False) zur Laufzeit verwendet werden, um festzustellen, ob ein Objekt obj als final markiert wurde. Wenn das dekorierte Objekt das Setzen von Attributen nicht unterstützt, gibt der Dekorator das Objekt unverändert zurück, ohne eine Ausnahme auszulösen.

@typing.no_type_check

Dekorator, um anzuzeigen, dass Annotationen keine Typenhinweise sind.

Dies funktioniert als Klassen- oder FunktionsDekorator. Bei einer Klasse wird dies rekursiv auf alle in dieser Klasse definierten Methoden und Klassen angewendet (aber nicht auf Methoden, die in ihren Oberklassen oder Unterklassen definiert sind). Typ-Checker ignorieren alle Annotationen in einer Funktion oder Klasse mit diesem Dekorator.

@no_type_check verändert das dekorierte Objekt direkt.

@typing.no_type_check_decorator

Dekorator, um einem anderen Dekorator den no_type_check()-Effekt zu verleihen.

Dies umschließt den Dekorator mit etwas, das die dekorierte Funktion mit no_type_check() umschließt.

Veraltet seit Version 3.13, wird entfernt in Version 3.15: Kein Typ-Checker hat jemals Unterstützung für @no_type_check_decorator hinzugefügt. Er ist daher veraltet und wird in Python 3.15 entfernt.

@typing.override

Dekorator, um anzuzeigen, dass eine Methode in einer Unterklasse dazu bestimmt ist, eine Methode oder ein Attribut einer Oberklasse zu überschreiben.

Typ-Checker sollten einen Fehler ausgeben, wenn eine mit @override dekorierte Methode tatsächlich nichts überschreibt. Dies hilft, Fehler zu vermeiden, die auftreten können, wenn eine Basisklasse geändert wird, ohne dass eine entsprechende Änderung in einer Kindklasse vorgenommen wird.

Zum Beispiel

class Base:
    def log_status(self) -> None:
        ...

class Sub(Base):
    @override
    def log_status(self) -> None:  # Okay: overrides Base.log_status
        ...

    @override
    def done(self) -> None:  # Error reported by type checker
        ...

Es gibt keine Laufzeitüberprüfung dieser Eigenschaft.

Der Dekorator versucht, ein Attribut __override__ auf True des dekorierten Objekts zu setzen. Daher kann eine Überprüfung wie if getattr(obj, "__override__", False) zur Laufzeit verwendet werden, um festzustellen, ob ein Objekt obj als überschrieben markiert wurde. Wenn das dekorierte Objekt das Setzen von Attributen nicht unterstützt, gibt der Dekorator das Objekt unverändert zurück, ohne eine Ausnahme auszulösen.

Weitere Einzelheiten finden Sie in PEP 698.

Hinzugefügt in Version 3.12.

@typing.type_check_only

Dekorator, um eine Klasse oder Funktion als zur Laufzeit nicht verfügbar zu markieren.

Dieser Dekorator ist selbst zur Laufzeit nicht verfügbar. Er dient hauptsächlich dazu, Klassen zu markieren, die in Typ-Stub-Dateien definiert sind, wenn eine Implementierung eine Instanz einer privaten Klasse zurückgibt.

@type_check_only
class Response:  # private or not available at runtime
    code: int
    def get_header(self, name: str) -> str: ...

def fetch_response() -> Response: ...

Beachten Sie, dass die Rückgabe von Instanzen privater Klassen nicht empfohlen wird. Es ist normalerweise vorzuziehen, solche Klassen öffentlich zu machen.

Introspektionshilfen

typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False)

Gibt ein Wörterbuch mit Typenhinweisen für ein Funktions-, Methoden-, Modul- oder Klassenobjekt zurück.

Dies ist oft dasselbe wie obj.__annotations__, aber diese Funktion nimmt die folgenden Änderungen am Annotationswörterbuch vor:

  • Vorwärtsverweise, die als Zeichenkettenliterale oder ForwardRef-Objekte kodiert sind, werden durch Auswertung in globalns, localns und (wo zutreffend) dem Typenparameter-Namensraum von obj behandelt. Wenn globalns oder localns nicht angegeben sind, werden entsprechende Namensraum-Wörterbücher aus obj abgeleitet.

  • None wird durch types.NoneType ersetzt.

  • Wenn @no_type_check auf obj angewendet wurde, wird ein leeres Wörterbuch zurückgegeben.

  • Wenn obj eine Klasse C ist, gibt die Funktion ein Wörterbuch zurück, das Annotationen von Basisklassen von C mit denen von C direkt zusammenführt. Dies geschieht durch Traversierung von C.__mro__ und iteratives Kombinieren von __annotations__-Wörterbüchern. Annotationen in Klassen, die früher in der Methodenauflösungsreihenfolge erscheinen, haben immer Vorrang vor Annotationen in Klassen, die später in der Methodenauflösungsreihenfolge erscheinen.

  • Die Funktion ersetzt rekursiv alle Vorkommen von Annotated[T, ...] durch T, es sei denn, include_extras ist auf True gesetzt (siehe Annotated für weitere Informationen).

Siehe auch annotationlib.get_annotations(), eine untergeordnete Funktion, die Annotationen direkter zurückgibt.

Vorsicht

Diese Funktion kann beliebigen Code ausführen, der in Annotationen enthalten ist. Siehe Sicherheitsaspekte der Introspektion von Annotationen für weitere Informationen.

Hinweis

Wenn Vorwärtsverweise in den Annotationen von obj nicht auflösbar sind oder kein gültiger Python-Code sind, löst diese Funktion eine Ausnahme wie NameError aus. Dies kann beispielsweise bei importierten Typen-Aliase der Fall sein, die Vorwärtsverweise enthalten, oder bei Namen, die unter if TYPE_CHECKING importiert wurden.

Geändert in Version 3.9: Der Parameter include_extras wurde als Teil von PEP 593 hinzugefügt. Weitere Informationen finden Sie in der Dokumentation zu Annotated.

Geändert in Version 3.11: Zuvor wurde Optional[t] für Funktions- und Methodenannotationen hinzugefügt, wenn ein Standardwert gleich None gesetzt war. Jetzt wird die Annotation unverändert zurückgegeben.

typing.get_origin(tp)

Holen Sie sich die nicht subscriptete Version eines Typs: für ein Tippobjekt der Form X[Y, Z, ...] geben Sie X zurück.

Wenn X ein Alias des typing-Moduls für eine eingebaute Klasse oder eine Klasse aus dem collections-Modul ist, wird sie zur ursprünglichen Klasse normalisiert. Wenn X eine Instanz von ParamSpecArgs oder ParamSpecKwargs ist, geben Sie das zugrunde liegende ParamSpec zurück. Geben Sie None für nicht unterstützte Objekte zurück.

Beispiele

assert get_origin(str) is None
assert get_origin(Dict[str, int]) is dict
assert get_origin(Union[int, str]) is Union
assert get_origin(Annotated[str, "metadata"]) is Annotated
P = ParamSpec('P')
assert get_origin(P.args) is P
assert get_origin(P.kwargs) is P

Hinzugefügt in Version 3.8.

typing.get_args(tp)

Holen Sie sich Typargumente mit allen durchgeführten Substitutionen: für ein Tippobjekt der Form X[Y, Z, ...] geben Sie (Y, Z, ...) zurück.

Wenn X eine Union oder Literal ist, die in einem anderen generischen Typ enthalten ist, kann die Reihenfolge von (Y, Z, ...) aufgrund des Typ-Cachings von der Reihenfolge der ursprünglichen Argumente [Y, Z, ...] abweichen. Geben Sie () für nicht unterstützte Objekte zurück.

Beispiele

assert get_args(int) == ()
assert get_args(Dict[int, str]) == (int, str)
assert get_args(Union[int, str]) == (int, str)

Hinzugefügt in Version 3.8.

typing.get_protocol_members(tp)

Gibt die Menge der in einem Protocol definierten Mitglieder zurück.

>>> from typing import Protocol, get_protocol_members
>>> class P(Protocol):
...     def a(self) -> str: ...
...     b: int
>>> get_protocol_members(P) == frozenset({'a', 'b'})
True

Löst TypeError für Argumente aus, die keine Protokolle sind.

Hinzugefügt in Version 3.13.

typing.is_protocol(tp)

Bestimmen Sie, ob ein Typ ein Protocol ist.

Zum Beispiel

class P(Protocol):
    def a(self) -> str: ...
    b: int

is_protocol(P)    # => True
is_protocol(int)  # => False

Hinzugefügt in Version 3.13.

typing.is_typeddict(tp)

Prüfen Sie, ob ein Typ ein TypedDict ist.

Zum Beispiel

class Film(TypedDict):
    title: str
    year: int

assert is_typeddict(Film)
assert not is_typeddict(list | str)

# TypedDict is a factory for creating typed dicts,
# not a typed dict itself
assert not is_typeddict(TypedDict)

Hinzugefügt in Version 3.10.

class typing.ForwardRef

Klasse, die für die interne Typenrepräsentation von Zeichenketten-Vorwärtsverweisen verwendet wird.

Zum Beispiel wird List["SomeClass"] implizit in List[ForwardRef("SomeClass")] umgewandelt. ForwardRef sollte nicht von einem Benutzer instanziiert werden, kann aber von Introspektionswerkzeugen verwendet werden.

Hinweis

PEP 585 generische Typen wie list["SomeClass"] werden nicht implizit in list[ForwardRef("SomeClass")] umgewandelt und werden daher nicht automatisch zu list[SomeClass] aufgelöst.

Hinzugefügt in Version 3.7.4.

Geändert in Version 3.14: Dies ist jetzt ein Alias für annotationlib.ForwardRef. Mehrere undokumentierte Verhaltensweisen dieser Klasse wurden geändert; zum Beispiel wird nach der Auswertung eines ForwardRef der ausgewertete Wert nicht mehr zwischengespeichert.

typing.evaluate_forward_ref(forward_ref, *, owner=None, globals=None, locals=None, type_params=None, format=annotationlib.Format.VALUE)

Werten Sie eine annotationlib.ForwardRef als Typenhinweis aus.

Dies ähnelt dem Aufruf von annotationlib.ForwardRef.evaluate(), aber im Gegensatz zu dieser Methode wertet evaluate_forward_ref() auch Vorwärtsverweise aus, die innerhalb des Typenhinweises verschachtelt sind, rekursiv aus.

Siehe die Dokumentation für annotationlib.ForwardRef.evaluate() für die Bedeutung der Parameter owner, globals, locals, type_params und format.

Vorsicht

Diese Funktion kann beliebigen Code ausführen, der in Annotationen enthalten ist. Siehe Sicherheitsaspekte der Introspektion von Annotationen für weitere Informationen.

Hinzugefügt in Version 3.14.

typing.NoDefault

Ein Sentinel-Objekt, das verwendet wird, um anzuzeigen, dass ein Typenparameter keinen Standardwert hat. Zum Beispiel

>>> T = TypeVar("T")
>>> T.__default__ is typing.NoDefault
True
>>> S = TypeVar("S", default=None)
>>> S.__default__ is None
True

Hinzugefügt in Version 3.13.

Konstante

typing.TYPE_CHECKING

Eine spezielle Konstante, die von externen statischen Typ-Checkern als True angenommen wird. Zur Laufzeit ist sie False.

Ein Modul, dessen Import aufwendig ist und das nur Typen enthält, die für Typenannotationen verwendet werden, kann sicher innerhalb eines if TYPE_CHECKING:-Blocks importiert werden. Dies verhindert, dass das Modul zur Laufzeit tatsächlich importiert wird; Annotationen werden nicht eifrig ausgewertet (siehe PEP 649), daher ist die Verwendung nicht definierter Symbole in Annotationen harmlos – solange Sie sie nicht später untersuchen. Ihr statisches Typanalyse-Tool setzt TYPE_CHECKING während der statischen Typanalyse auf True, was bedeutet, dass das Modul importiert wird und die Typen während der Analyse ordnungsgemäß geprüft werden.

Verwendung

if TYPE_CHECKING:
    import expensive_mod

def fun(arg: expensive_mod.SomeType) -> None:
    local_var: expensive_mod.AnotherType = other_fun()

Wenn Sie gelegentlich Typenannotationen zur Laufzeit untersuchen müssen, die nicht definierte Symbole enthalten könnten, verwenden Sie annotationlib.get_annotations() mit einem format-Parameter von annotationlib.Format.STRING oder annotationlib.Format.FORWARDREF, um die Annotationen sicher abzurufen, ohne NameError auszulösen.

Hinzugefügt in Version 3.5.2.

Veraltete Aliase

Dieses Modul definiert mehrere veraltete Aliase für bereits vorhandene Standardbibliotheksklassen. Diese wurden ursprünglich in das typing-Modul aufgenommen, um die Parametrisierung dieser generischen Klassen mit [] zu unterstützen. Die Aliase wurden jedoch in Python 3.9 überflüssig, als die entsprechenden vorhandenen Klassen für die Unterstützung von [] erweitert wurden (siehe PEP 585).

Die redundanten Typen sind ab Python 3.9 veraltet. Obwohl die Aliase irgendwann entfernt werden könnten, ist die Entfernung dieser Aliase derzeit nicht geplant. Daher werden von der Interpreter für diese Aliase keine Deprecation-Warnungen ausgegeben.

Wenn zu einem späteren Zeitpunkt beschlossen wird, diese veralteten Aliase zu entfernen, wird die Interpreter mindestens zwei Releases vor der Entfernung eine Deprecation-Warnung ausgeben. Die Aliase werden garantiert bis mindestens Python 3.14 ohne Deprecation-Warnungen im typing-Modul vorhanden sein.

Typ-Checker werden ermutigt, die Verwendung der veralteten Typen zu kennzeichnen, wenn das von ihnen geprüfte Programm eine minimale Python-Version von 3.9 oder neuer anstrebt.

Aliase für eingebaute Typen

class typing.Dict(dict, MutableMapping[KT, VT])

Veralteter Alias für dict.

Beachten Sie, dass es zur Annotation von Argumenten bevorzugt wird, einen abstrakten Sammlungstyp wie Mapping zu verwenden, anstatt dict oder typing.Dict zu verwenden.

Veraltet seit Version 3.9: builtins.dict unterstützt jetzt das Subscripting ([]). Siehe PEP 585 und Generischer Alias-Typ.

class typing.List(list, MutableSequence[T])

Veralteter Alias für list.

Beachten Sie, dass es zur Annotation von Argumenten bevorzugt wird, einen abstrakten Sammlungstyp wie Sequence oder Iterable zu verwenden, anstatt list oder typing.List zu verwenden.

Veraltet seit Version 3.9: builtins.list unterstützt jetzt das Subscripting ([]). Siehe PEP 585 und Generischer Alias-Typ.

class typing.Set(set, MutableSet[T])

Veralteter Alias für builtins.set.

Beachten Sie, dass es zur Annotation von Argumenten bevorzugt wird, einen abstrakten Sammlungstyp wie collections.abc.Set zu verwenden, anstatt set oder typing.Set zu verwenden.

Veraltet seit Version 3.9: builtins.set unterstützt jetzt das Subscripting ([]). Siehe PEP 585 und Generischer Alias-Typ.

class typing.FrozenSet(frozenset, AbstractSet[T_co])

Veralteter Alias für builtins.frozenset.

Veraltet seit Version 3.9: builtins.frozenset unterstützt jetzt das Subscripting ([]). Siehe PEP 585 und Generischer Alias-Typ.

typing.Tuple

Veralteter Alias für tuple.

tuple und Tuple sind im Typensystem speziell behandelt; siehe Annotation von Tupeln für weitere Details.

Veraltet seit Version 3.9: builtins.tuple unterstützt jetzt das Subscripting ([]). Siehe PEP 585 und Generischer Alias-Typ.

class typing.Type(Generic[CT_co])

Veralteter Alias für type.

Siehe Der Typ von Klassenobjekten für Details zur Verwendung von type oder typing.Type in Typannotationen.

Hinzugefügt in Version 3.5.2.

Veraltet seit Version 3.9: builtins.type unterstützt jetzt das Subscripting ([]). Siehe PEP 585 und Generischer Alias-Typ.

Aliase für Typen in collections

class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])

Veralteter Alias für collections.defaultdict.

Hinzugefügt in Version 3.5.2.

Veraltet seit Version 3.9: collections.defaultdict unterstützt jetzt das Subscripting ([]). Siehe PEP 585 und Generischer Alias-Typ.

class typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])

Veralteter Alias für collections.OrderedDict.

Hinzugefügt in Version 3.7.2.

Veraltet seit Version 3.9: collections.OrderedDict unterstützt jetzt das Subscripting ([]). Siehe PEP 585 und Generischer Alias-Typ.

class typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT])

Veralteter Alias für collections.ChainMap.

Hinzugefügt in Version 3.6.1.

Seit Version 3.9 veraltet: collections.ChainMap unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.Counter(collections.Counter, Dict[T, int])

Veralteter Alias für collections.Counter.

Hinzugefügt in Version 3.6.1.

Seit Version 3.9 veraltet: collections.Counter unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.Deque(deque, MutableSequence[T])

Veralteter Alias für collections.deque.

Hinzugefügt in Version 3.6.1.

Seit Version 3.9 veraltet: collections.deque unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

Aliase zu anderen konkreten Typen

class typing.Pattern
class typing.Match

Veraltete Aliase, die den Rückgabetypen von re.compile() und re.match() entsprechen.

Diese Typen (und die entsprechenden Funktionen) sind generisch über AnyStr. Pattern kann als Pattern[str] oder Pattern[bytes] spezialisiert werden; Match kann als Match[str] oder Match[bytes] spezialisiert werden.

Seit Version 3.9 veraltet: Die Klassen Pattern und Match aus re unterstützen jetzt []. Siehe PEP 585 und Generic Alias Type.

class typing.Text

Veralteter Alias für str.

Text wird bereitgestellt, um einen zukunftskompatiblen Pfad für Python 2-Code zu schaffen: in Python 2 ist Text ein Alias für unicode.

Verwenden Sie Text, um anzugeben, dass ein Wert einen Unicode-String auf eine Weise enthalten muss, die sowohl mit Python 2 als auch mit Python 3 kompatibel ist.

def add_unicode_checkmark(text: Text) -> Text:
    return text + u' \u2713'

Hinzugefügt in Version 3.5.2.

Seit Version 3.11 veraltet: Python 2 wird nicht mehr unterstützt, und die meisten Type-Checker unterstützen auch keine Typüberprüfung für Python 2-Code mehr. Die Entfernung des Alias ist derzeit nicht geplant, aber Benutzer werden ermutigt, str anstelle von Text zu verwenden.

Aliase zu Container-ABCs in collections.abc

class typing.AbstractSet(Collection[T_co])

Veralteter Alias für collections.abc.Set.

Seit Version 3.9 veraltet: collections.abc.Set unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.ByteString(Sequence[int])

Veralteter Alias für collections.abc.ByteString.

Verwenden Sie isinstance(obj, collections.abc.Buffer), um zur Laufzeit zu testen, ob obj das Pufferprotokoll implementiert. Für die Verwendung in Typannotationen verwenden Sie entweder Buffer oder eine Union, die explizit die Typen angibt, die Ihr Code unterstützt (z. B. bytes | bytearray | memoryview).

ByteString war ursprünglich als abstrakte Klasse gedacht, die als Obertyp für sowohl bytes als auch bytearray dienen sollte. Da die ABC jedoch nie Methoden hatte, war das Wissen, dass ein Objekt eine Instanz von ByteString war, nie wirklich nützlich über das Objekt. Andere gängige Puffertypen wie memoryview wurden auch nie als Untertypen von ByteString verstanden (weder zur Laufzeit noch von statischen Typprüfern).

Weitere Einzelheiten finden Sie in PEP 688.

Seit Version 3.9 veraltet, wird in Version 3.17 entfernt.

class typing.Collection(Sized, Iterable[T_co], Container[T_co])

Veralteter Alias für collections.abc.Collection.

Hinzugefügt in Version 3.6.

Seit Version 3.9 veraltet: collections.abc.Collection unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.Container(Generic[T_co])

Veralteter Alias für collections.abc.Container.

Seit Version 3.9 veraltet: collections.abc.Container unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.ItemsView(MappingView, AbstractSet[tuple[KT_co, VT_co]])

Veralteter Alias für collections.abc.ItemsView.

Seit Version 3.9 veraltet: collections.abc.ItemsView unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.KeysView(MappingView, AbstractSet[KT_co])

Veralteter Alias für collections.abc.KeysView.

Seit Version 3.9 veraltet: collections.abc.KeysView unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.Mapping(Collection[KT], Generic[KT, VT_co])

Veralteter Alias für collections.abc.Mapping.

Seit Version 3.9 veraltet: collections.abc.Mapping unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.MappingView(Sized)

Veralteter Alias für collections.abc.MappingView.

Seit Version 3.9 veraltet: collections.abc.MappingView unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.MutableMapping(Mapping[KT, VT])

Veralteter Alias für collections.abc.MutableMapping.

Seit Version 3.9 veraltet: collections.abc.MutableMapping unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.MutableSequence(Sequence[T])

Veralteter Alias für collections.abc.MutableSequence.

Seit Version 3.9 veraltet: collections.abc.MutableSequence unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.MutableSet(AbstractSet[T])

Veralteter Alias für collections.abc.MutableSet.

Seit Version 3.9 veraltet: collections.abc.MutableSet unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.Sequence(Reversible[T_co], Collection[T_co])

Veralteter Alias für collections.abc.Sequence.

Seit Version 3.9 veraltet: collections.abc.Sequence unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.ValuesView(MappingView, Collection[_VT_co])

Veralteter Alias für collections.abc.ValuesView.

Seit Version 3.9 veraltet: collections.abc.ValuesView unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

Aliase zu asynchronen ABCs in collections.abc

class typing.Coroutine(Awaitable[ReturnType], Generic[YieldType, SendType, ReturnType])

Veralteter Alias für collections.abc.Coroutine.

Siehe Annotating generators and coroutines für Details zur Verwendung von collections.abc.Coroutine und typing.Coroutine in Typannotationen.

Hinzugefügt in Version 3.5.3.

Seit Version 3.9 veraltet: collections.abc.Coroutine unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.AsyncGenerator(AsyncIterator[YieldType], Generic[YieldType, SendType])

Veralteter Alias für collections.abc.AsyncGenerator.

Siehe Annotating generators and coroutines für Details zur Verwendung von collections.abc.AsyncGenerator und typing.AsyncGenerator in Typannotationen.

Hinzugefügt in Version 3.6.1.

Seit Version 3.9 veraltet: collections.abc.AsyncGenerator unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

Seit Version 3.13 geändert: Der Parameter SendType hat jetzt einen Standardwert.

class typing.AsyncIterable(Generic[T_co])

Veralteter Alias für collections.abc.AsyncIterable.

Hinzugefügt in Version 3.5.2.

Seit Version 3.9 veraltet: collections.abc.AsyncIterable unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.AsyncIterator(AsyncIterable[T_co])

Veralteter Alias für collections.abc.AsyncIterator.

Hinzugefügt in Version 3.5.2.

Seit Version 3.9 veraltet: collections.abc.AsyncIterator unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.Awaitable(Generic[T_co])

Veralteter Alias für collections.abc.Awaitable.

Hinzugefügt in Version 3.5.2.

Seit Version 3.9 veraltet: collections.abc.Awaitable unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

Aliase zu anderen ABCs in collections.abc

class typing.Iterable(Generic[T_co])

Veralteter Alias für collections.abc.Iterable.

Seit Version 3.9 veraltet: collections.abc.Iterable unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

class typing.Iterator(Iterable[T_co])

Veralteter Alias für collections.abc.Iterator.

Seit Version 3.9 veraltet: collections.abc.Iterator unterstützt jetzt Indizierung ([]). Siehe PEP 585 und Generic Alias Type.

typing.Callable

Veraltete Alias für collections.abc.Callable.

Siehe Annotating callable objects für Details zur Verwendung von collections.abc.Callable und typing.Callable in Typ-Annotationen.

Veraltet seit Version 3.9: collections.abc.Callable unterstützt jetzt Subskriptionen ([]). Siehe PEP 585 und Generic Alias Type.

Geändert in Version 3.10: Callable unterstützt jetzt ParamSpec und Concatenate. Siehe PEP 612 für weitere Details.

class typing.Generator(Iterator[YieldType], Generic[YieldType, SendType, ReturnType])

Veraltete Alias für collections.abc.Generator.

Siehe Annotating generators and coroutines für Details zur Verwendung von collections.abc.Generator und typing.Generator in Typ-Annotationen.

Veraltet seit Version 3.9: collections.abc.Generator unterstützt jetzt Subskriptionen ([]). Siehe PEP 585 und Generic Alias Type.

Geändert in Version 3.13: Standardwerte für die Send- und Rückgabetypen wurden hinzugefügt.

class typing.Hashable

Veraltete Alias für collections.abc.Hashable.

Veraltet seit Version 3.12: Verwenden Sie stattdessen direkt collections.abc.Hashable.

class typing.Reversible(Iterable[T_co])

Veraltete Alias für collections.abc.Reversible.

Veraltet seit Version 3.9: collections.abc.Reversible unterstützt jetzt Subskriptionen ([]). Siehe PEP 585 und Generic Alias Type.

class typing.Sized

Veraltete Alias für collections.abc.Sized.

Veraltet seit Version 3.12: Verwenden Sie stattdessen direkt collections.abc.Sized.

Aliase für contextlib ABCs

class typing.ContextManager(Generic[T_co, ExitT_co])

Veraltete Alias für contextlib.AbstractContextManager.

Der erste Typparameter, T_co, repräsentiert den Typ, der von der Methode __enter__() zurückgegeben wird. Der optionale zweite Typparameter, ExitT_co, der standardmäßig bool | None ist, repräsentiert den Typ, der von der Methode __exit__() zurückgegeben wird.

Hinzugefügt in Version 3.5.4.

Veraltet seit Version 3.9: contextlib.AbstractContextManager unterstützt jetzt Subskriptionen ([]). Siehe PEP 585 und Generic Alias Type.

Geändert in Version 3.13: Der optionale zweite Typparameter ExitT_co wurde hinzugefügt.

class typing.AsyncContextManager(Generic[T_co, AExitT_co])

Veraltete Alias für contextlib.AbstractAsyncContextManager.

Der erste Typparameter, T_co, repräsentiert den Typ, der von der Methode __aenter__() zurückgegeben wird. Der optionale zweite Typparameter, AExitT_co, der standardmäßig bool | None ist, repräsentiert den Typ, der von der Methode __aexit__() zurückgegeben wird.

Hinzugefügt in Version 3.6.2.

Veraltet seit Version 3.9: contextlib.AbstractAsyncContextManager unterstützt jetzt Subskriptionen ([]). Siehe PEP 585 und Generic Alias Type.

Geändert in Version 3.13: Der optionale zweite Typparameter AExitT_co wurde hinzugefügt.

Zeitplan für die Veralterung wichtiger Funktionen

Bestimmte Funktionen in typing sind veraltet und könnten in einer zukünftigen Python-Version entfernt werden. Die folgende Tabelle fasst wichtige Veralterungen zur Bequemlichkeit zusammen. Dies kann sich ändern, und nicht alle Veralterungen sind aufgeführt.

Funktion

Veraltet in

Geplante Entfernung

PEP/Ausgabe

typing-Versionen von Standard-Sammlungen

3.9

Unentschieden (siehe Veraltete Aliase für weitere Informationen)

PEP 585

typing.ByteString

3.9

3.17

gh-91896

typing.Text

3.11

Unentschieden

gh-92332

typing.Hashable und typing.Sized

3.12

Unentschieden

gh-94309

typing.TypeAlias

3.12

Unentschieden

PEP 695

@typing.no_type_check_decorator

3.13

3.15

gh-106309

typing.AnyStr

3.13

3.18

gh-105578