Was bedeutet das Attribut __total__ dunder in Python 3?

17

In neu veröffentlichtem Python 3.8 gibt es eine neue Typanmerkung typing.TypedDict. In seiner Dokumentation wird dies erwähnt

Auf die Typinformationen für die Selbstbeobachtung kann über Point2D.__annotations__und zugegriffen werden Point2D.__total__. [....]

Obwohl __annotations__bekannt, dass ich in PEP 3107 eingeführt wurde , kann ich keine Informationen zu finden __total__. Könnte jemand seine Bedeutung erklären und wenn möglich auf maßgebliche Quellen verweisen?

Antti Haapala
quelle
4
Typisch. 99% der typingInterna sind nicht dokumentiert, und der Teil, der schlecht dokumentiert ist.
Aran-Fey

Antworten:

3

Ich vermute, dass das __total__Feld angibt, ob Instanzen vollständig sein müssen (Standardeinstellung) oder nicht (alle Felder optional). Ich begann meine Suche bei PEP 589 , das TypedDictdie Totalität als solche einführte und beschrieb. Es wurde ein totalArgument verwendet, das sinnvoll wäre, den Dunder-Stil für die class Syntax umzubenennen . Ich habe jedoch nicht herausgefunden, wann eine solche Umbenennung stattgefunden hat.

Bei MyPy, dem eigentlichen Typprüfer, der sich um diese Anmerkungen kümmert, gibt es eine ähnliche Dokumentation TypedDictund Gesamtheit , aber auch hier keinen Verweis auf die Dunder-Syntax. Das TypedDictTypeEingraben in die Implementierung führte zu mehr Verwirrung, da in types.py kein Gesamtfeld vorhanden ist, sondern separate itemsund required_keys. Totalität würde dies implizieren, items.keys()==required_keysaber die Implementierung macht andere Annahmen, wie can_be_falsesich itemsallein zu verlassen.total=Falsesollte im prinzip bedeuten required_keysist leer.

Die CPython-Quelle für _TypedDictMeta zeigt zumindest, dass das totalArgument und der __total__Dunder ein und dasselbe sind, obwohl die Quelle sich TypedDictselbst als "kann bald hinzugefügt werden" beschreibt.

Yann Vernier
quelle
Akzeptiere dies für jetzt - wenn nicht irgendetwas anderes, wird es vielleicht andere eher bereit machen, sich zu melden und deine Antwort zu widerlegen: D
Antti Haapala
Ich persönlich vermute, can_be_falsedass es sich um einen MyPy-Fehler handelt, der möglicherweise darauf zurückzuführen ist, dass von Anfang an keine optionalen Felder geplant waren.
Yann Vernier
1

TypedDictwurde in Python 3.8 über PEP 589 akzeptiert . In Python scheint __total__es sich um ein boolesches Flag zu handeln, das Truestandardmäßig auf Folgendes gesetzt ist :

tot = TypedDict.__total__
print(type(tot))
print(tot)

# <class 'bool'>
# True

Wie in anderen Beiträgen erwähnt, sind Details zu dieser Methode in den Dokumenten begrenzt , aber der Link von @Yann Vernier zum CPython-Quellcode deutet stark darauf hin, dass er __total__mit dem in Python 3.8 eingeführten neuen totalSchlüsselwort zusammenhängt :

# cypthon/typing.py

class _TypedDictMeta(type):
    def __new__(cls, name, bases, ns, total=True):
        """Create new typed dict class object.
        ...
        """
        ...
        if not hasattr(tp_dict, '__total__'):
            tp_dict.__total__ = total
        ...

Wie funktioniert es?

Synopsis : Standardmäßig sind alle Schlüssel erforderlich, um eine definierte Instanz zu instanziieren TypedDict. total=Falseüberschreibt diese Einschränkung und erlaubt optionale Schlüssel. Siehe die folgende Demonstration.

Gegeben

Ein Testverzeichnisbaum:

Geben Sie hier die Bildbeschreibung ein

Code

Dateien im Testverzeichnis:

# rgb_bad.py

from typing import TypedDict


class Color(TypedDict):
    r: int
    g: int
    b: int
    a: float


blue = Color(r=0, g=0, b=255)                     # missing "a"

# rgb_good.py

from typing import TypedDict


class Color(TypedDict, total=False):
    r: int
    g: int
    b: int
    a: float


blue = Color(r=0, g=0, b=255)                     # missing "a"

Demo

Wenn ein Schlüssel fehlt, beschwert sich mypy über die Befehlszeile:

> mypy code/rgb_bad.py
code\rgb_bad.py:11: error: Key 'a' missing for TypedDict "Color"
...

Die Einstellung total=Falseerlaubt optionale Schlüssel:

> mypy code/rgb_good.py
Success: no issues found in 1 source file

Siehe auch

  • Tweet von R. Hettinger demonstriert die Totalität
  • PEP- Abschnitt zur Gesamtheit in PEP 589
  • Artikel Abschnitt über Typen und TypedDictin Python 3.8 von Real Python
  • typing-extensionsPaket zur Verwendung TypedDictin Python 3.5, 3.6
Pylang
quelle