Diferencia entre definir typing.Dict y dict?

102

Estoy practicando el uso de sugerencias de tipo en Python 3.5. Uno de mis colegas usa typing.Dict:

import typing


def change_bandwidths(new_bandwidths: typing.Dict,
                      user_id: int,
                      user_name: str) -> bool:
    print(new_bandwidths, user_id, user_name)
    return False


def my_change_bandwidths(new_bandwidths: dict,
                         user_id: int,
                         user_name: str) ->bool:
    print(new_bandwidths, user_id, user_name)
    return True


def main():
    my_id, my_name = 23, "Tiras"
    simple_dict = {"Hello": "Moon"}
    change_bandwidths(simple_dict, my_id, my_name)
    new_dict = {"new": "energy source"}
    my_change_bandwidths(new_dict, my_id, my_name)

if __name__ == "__main__":
    main()

Ambos funcionan bien, no parece haber diferencia.

He leído la typingdocumentación del módulo .

¿Entre typing.Dicto dictcuál debo usar en el programa?

Sarit
fuente
11
Tenga en cuenta que Python en realidad no aplica las sugerencias de tipo. Son solo sugerencias , no se usan en tiempo de ejecución, ni siquiera en tiempo de compilación, para hacer cumplir los tipos. Python puede estar fuertemente tipado (opuesto a tipeo débil), también se teclea dinámicamente (opuesto al tipado estricto). Consulte ¿Está Python fuertemente tipado? . Sin embargo, herramientas externas como mypy pueden usar estas sugerencias para ayudarlo a escribir un mejor código en un proceso llamado análisis estático.
Martijn Pieters
1
@MartijnPieters Me encantaba usar sugerencias de tipos en mi código junto con MyPy y pretender que podía usar Python con seguridad de tipos. Desafortunadamente, obtuve un código A) que no funciona en <3.4 y B) gente que se ríe de mí porque aparentemente, las pistas de tipo son un hazmerreír. Realmente es bastante lamentable.
gato
3
@cat: Un empleado de Facebook introdujo la sugerencia de tipo en Python, porque tuvimos un gran éxito al agregar la misma función a PHP (ver truco ). Cualquiera que se ría nunca ha construido un gran proyecto con más de un puñado de ingenieros.
Martijn Pieters
3
@MartijnPieters No, def a(b: int) -> bool:es un error de sintaxis en Python 2.7, y creo que también es un error de sintaxis en versiones anteriores de Python 3.
gato
1
@cat: estás hablando de anotaciones de funciones aquí, sintaxis que se agregó a Python 3.0. Entonces, la única versión en la que hay un error de sintaxis es 2.7, por lo que mypy admite poner esa información en los comentarios.
Martijn Pieters

Respuestas:

138

No hay una diferencia real entre usar un simple typing.Dictydict no.

Sin embargo, typing.Dictes un tipo genérico que le permite especificar el tipo de claves y valores también , haciéndolo más flexible:

def change_bandwidths(new_bandwidths: typing.Dict[str, str],
                      user_id: int,
                      user_name: str) -> bool:

Como tal, podría ser que en algún momento de la vida de su proyecto desee definir el argumento del diccionario con un poco más de precisión, momento en el que expandir typing.Dicta typing.Dict[key_type, value_type]es un cambio 'menor' que reemplazardict .

Puede hacer esto aún más genérico usando Mappingo MutableMappingtipos aquí; dado que su función no necesita alterar el mapeo, me quedo con Mapping. A dictes un mapeo, pero puede crear otros objetos que también satisfagan la interfaz de mapeo, y su función podría seguir funcionando con esos:

def change_bandwidths(new_bandwidths: typing.Mapping[str, str],
                      user_id: int,
                      user_name: str) -> bool:

Ahora le está diciendo claramente a otros usuarios de esta función que su código en realidad no alterará el new_bandwidthsmapeo pasado.

Su implementación real solo espera un objeto que sea imprimible. Esa puede ser una implementación de prueba, pero tal como está, su código continuaría funcionando si lo usara new_bandwidths: typing.Any, porque cualquier objeto en Python es imprimible.

Martijn Pieters
fuente
2
Ejemplos adicionales útiles serían cuando los valores del diccionario pueden ser de diferentes tipos {"name": "bob", "age" : 51}, por ejemplo , ¿sería algo así como typing.Mapping[Union[str, int]? ¿Qué pasa con un diccionario anidado como {"person": {"name":"bob", "age": 51}sería algo así typing.Mapping[str, typing.Mapping[Union[str, int]]? Usarlo Unionasí me preocupa porque no es un esquema estricto, ya que no hay pedidos. Quizás eso esté bien, ¿o hay alguna alternativa?
Davos
1
No importa la Unionpregunta, veo que sigue siendo una discusión abierta github.com/python/typing/issues/28
Davos
1
Esto parece ser muy interesante, útil y relacionado python.org/dev/peps/pep-0589
Greg Hilston
@GregHilston: en realidad se trata de cómo restringir las claves que puede contener un diccionario y especificar qué tipos debe tener cada valor asociado.
Martijn Pieters
1
@GregHilston: ah, sí, lo es.
Martijn Pieters
26

typing.Dictes una versión genérica de dict:

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

Una versión genérica de dict. El uso de este tipo es el siguiente:

def get_position_in_index(word_list: Dict[str, int], word: str) -> int:
     return word_list[word]

Aquí puede especificar el tipo de clave y valores en el dict: Dict[str, int]

AKS
fuente