Quelle est la signification de l'attribut __total__ dunder dans Python 3?

17

Dans la nouvelle version de Python 3.8, il y a une nouvelle annotation de type typing.TypedDict. Sa documentation mentionne que

Les informations de type pour l'introspection sont accessibles via Point2D.__annotations__et Point2D.__total__. [....]

Bien que cela __annotations__soit bien connu, ayant été introduit dans le PEP 3107 , je ne trouve aucune information sur __total__. Quelqu'un pourrait-il expliquer sa signification et, si possible, son lien avec des sources faisant autorité?

Antti Haapala
la source
4
Typique. 99% des typinginternes ne sont pas documentés et la partie qui est mal documentée.
Aran-Fey

Réponses:

3

Je suppose que le __total__champ signifie si les instances doivent être complètes (par défaut) ou non (tous les champs sont facultatifs). J'ai commencé ma recherche au PEP 589 , qui a présenté TypedDictet décrit la totalité comme telle. Il a utilisé un totalargument, qu'il serait judicieux de renommer dunder-style pour la class syntaxe. Cependant, je n'ai pas trouvé quand un tel changement de nom a eu lieu.

En examinant MyPy, qui est le vérificateur de type réel qui se soucie de ces annotations, il existe une documentation TypedDictet une totalité similaires , mais encore une fois aucune référence à la syntaxe du dunder. Creuser dans son implémentation a conduit à plus de confusion, car TypedDictTypedans types.py n'a pas un champ total, mais séparé itemset required_keys. La totalité impliquerait cela, items.keys()==required_keysmais la mise en œuvre fait des hypothèses différentes, comme can_be_falses'appuyer itemsuniquement sur . total=Falsedevrait en principe signifier required_keysest vide.

La source CPython pour _TypedDictMeta révèle au moins que l' totalargument et le __total__dunder sont une seule et même chose, bien que la source se décrit TypedDictcomme "pourrait être ajoutée bientôt".

Yann Vernier
la source
Accepter ceci pour le moment - sinon rien d'autre, peut-être que cela rendra les autres plus disposés à se manifester et à réfuter votre réponse: D
Antti Haapala
can_be_falsePersonnellement, je soupçonne que la chose est un bogue MyPy, probablement lié au fait de ne pas avoir prévu d'avoir des champs facultatifs dès le début.
Yann Vernier
1

TypedDicta été accepté dans Python 3.8 via PEP 589 . Depuis Python, il apparaît que __total__c'est un drapeau booléen défini Truepar défaut:

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

# <class 'bool'>
# True

Comme mentionné dans d'autres articles, les détails de cette méthode sont limités dans la documentation , mais le lien de @Yann Vernier vers le code source CPython suggère fortement qu'il __total__est lié au nouveau totalmot-clé introduit dans Python 3.8 :

# 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
        ...

Comment ça marche?

Synopsis : par défaut, toutes les clés sont requises lors de l'instanciation d'une définition TypedDict. total=Falseoutrepasse cette restriction et autorise les clés facultatives. Voir la démonstration suivante.

Donné

Une arborescence de répertoires de test:

entrez la description de l'image ici

Code

Fichiers dans le répertoire de test:

# 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"

Démo

Si une clé est manquante, mypy se plaindra à la ligne de commande:

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

Le réglage total=Falsepermet des clés optionnelles:

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

Voir également

  • Tweet de R. Hettinger démontrant la totalité
  • Section PEP sur la totalité dans PEP 589
  • Article Section sur les types et TypedDicten Python 3.8 par Real Python
  • typing-extensionspackage à utiliser TypedDictdans Python 3.5, 3.6
pylang
la source