web-dev-qa-db-fra.com

Comment spécifier les types OrderedDict K, V pour l'annotation de type Mypy?

J'utilise Python 3.5 avec Mypy pour avoir une vérification statique de base pour mon script. Récemment, j'ai refactorisé certaines méthodes pour renvoyer OrderedDict, mais je suis tombé sur une erreur "'type' object is not subscriptable", quand j'ai essayé d'utiliser l'annotation de retour avec les types Key et Value spécifiés.

Exemple réduit:

#!/usr/bin/env python3.5

from collections import OrderedDict

# this works
def foo() -> OrderedDict:
    result = OrderedDict() # type: OrderedDict[str, int]
    result['foo'] = 123
    return result

# this doesn't
def foo2() -> OrderedDict[str, int]:
    result = OrderedDict() # type: OrderedDict[str, int]
    result['foo'] = 123
    return result

print(foo())

Et ceci est python sortie quand il est exécuté:

Traceback (most recent call last):
  File "./foo.py", line 12, in <module>
    def foo2() -> OrderedDict[str, int]:
TypeError: 'type' object is not subscriptable

Mypy n'a cependant aucun problème avec l'annotation de type en commentaire et va en fait avertir si j'essaye de faire result[123] = 123.

Quelle est la cause de cela?

24
Xarn

Il n'y a pas de problème dans mypy (du moins, pas en 0.501). Mais il y a is un problème avec Python 3.6.0. Considérez ce qui suit:

from collections import OrderedDict
from typing import Dict

def foo() -> Dict[str, int]:
    result: OrderedDict[str, int] = OrderedDict()
    result['two'] = 2
    return result

Ce code satisfera à la fois mypy (0.501) et Python (3.6.0). Cependant, si vous remplacez Dict par OrderedDict, alors mypy sera toujours heureux, mais son exécution mourra avec TypeError: 'type' object is not subscriptable.

Il est intéressant de noter que l'interpréteur Python meurt en voyant un OrderedDict en indice dans la signature de la fonction, mais est heureux de l'accepter dans une annotation de type variable.

Quoi qu'il en soit, ma solution consiste à utiliser Dict au lieu de OrderedDict dans la signature de la fonction (et ajouter un commentaire que cela devrait être corrigé si/quand le Python l'interprète apprendra à accepter la signature correcte).

20
Oren Ben-Kiki

Comme solution de contournement, vous pouvez également mettre le type de retour dans une chaîne pour satisfaire à la fois Mypy et Python 3.6:

from collections import OrderedDict

def foo() -> 'OrderedDict[str, int]':
    result = OrderedDict()
    result['foo'] = 123
    return result
11
Dion

Vous pouvez également essayer d'utiliser MutableMapping (comme dans cette réponse: https://stackoverflow.com/a/44167921/138661 )

from collections import OrderedDict
from typing import Dict

def foo() -> MutableMapping[str, int]:
    result = OrderedDict() # type: MutableMapping[str, int]
    result['foo'] = 123
    return result
2
Arany