¿Diferencia entre definir la tipificación.Dict y dict?

1 minuto de lectura

avatar de usuario
José

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 ninguna diferencia.

He leído el typing documentación del módulo.

Entre typing.Dict o dict ¿Cuál debo usar en el programa?

  • Tenga en cuenta que Python en realidad no hacer cumplir sugerencias de tipo. Están solo sugerencias, no se usan en tiempo de ejecución, ni siquiera en tiempo de compilación, para aplicar tipos. Python puede estar fuertemente tipado (opuesto a débil tipeado), también es escrito dinámicamente (opuesto a tipificación estricta). Consulte ¿Python está fuertemente tipado?. Sin embargo, las 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

    7 mayo 2016 a las 11:04

  • @MartijnPieters Me encantaba usar sugerencias de tipo en mi código junto con MyPy y fingir que podía usar Python con seguridad de tipo. Desafortunadamente, me consiguió A) un código que no funciona en <3.4 y B) la gente se ríe de mí porque aparentemente, las sugerencias de tipo son el hazmerreír. Es realmente bastante desafortunado.

    – gato

    7 mayo 2016 a las 15:40

  • @cat: La sugerencia de tipo fue introducida en Python por un empleado de Facebook, porque teníamos enorme éxito al agregar la misma característica a PHP (ver cortar a tajos). Cualquiera que se ría nunca ha construido un gran proyecto con más de un puñado de ingenieros.

    – Martijn Pieters

    7 mayo 2016 a las 15:44


  • @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

    7 mayo 2016 a las 15:49


  • @cat: estás hablando anotaciones de funciones aquí, la sintaxis que se agregó a Python 3.0. Entonces, la única versión en la que se trata de un error de sintaxis es la 2.7, por lo que mypy admite incluir esa información en los comentarios.

    – Martijn Pieters

    7 mayo 2016 a las 16:58

avatar de usuario
Martijn Pieters

No hay una diferencia real entre usar un simple typing.Dict y dictno.

Sin embargo, typing.Dict es un Tipo genérico * que le permite especificar el tipo de las claves y valores tambiénhaciéndolo más flexible:

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

Como tal, bien 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.Dict a typing.Dict[key_type, value_type] es un cambio ‘más pequeño’ que reemplazar dict.

Puedes hacer esto aún más genérico usando Mapping o MutableMapping tipos aquí; ya que su función no necesita alterar el mapeo, me quedaría con Mapping. A dict es un mapeo, pero podría crear otros objetos que también satisfagan la interfaz de mapeo, y su función aún podría funcionar 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 la new_bandwidths mapeo pasado.

Su implementación real simplemente 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 usara new_bandwidths: typing.Anyporque cualquier objeto en Python es imprimible.


*: Nota: si está usando Python 3.7 o más reciente, puede usar dict como un tipo genérico si comienza su módulo con from __future__ import annotationsy a partir de Python 3.9, dict (así como otros contenedores estándar) admite el uso como tipo genérico incluso sin esa directiva.

  • Ejemplos adicionales útiles serían cuando los valores del diccionario pueden ser de diferentes tipos, por ejemplo {"name": "bob", "age" : 51}sería algo comotyping.Mapping[Union[str, int] ? ¿Qué pasa con un diccionario anidado como {"person": {"name":"bob", "age": 51} sería algo como typing.Mapping[str, typing.Mapping[Union[str, int]] ? Usando Union así me preocupa porque no es un esquema estricto ya que no hay orden. Tal vez eso está bien, o hay una alternativa?

    – Davos

    4 de junio de 2018 a las 15:07

  • No importa sobre el Union pregunta veo que sigue siendo una discusión abierta github.com/python/typing/issues/28

    – Davos

    04/06/2018 a las 15:15

  • Esto me parece muy interesante, útil y relacionado. python.org/dev/peps/pep-0589

    – Greg Hilton

    21 de agosto de 2019 a las 15:08

  • @GregHilston: ah, sí, lo es.

    – Martijn Pieters

    21 de agosto de 2019 a las 16:50

  • @xjcl: ver Ver python.org/dev/peps/pep-0484/#covariance-and-contravariance para más.

    – Martijn Pieters

    13 de diciembre de 2020 a las 12:26

typing.Dict es 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]

avatar de usuario
Ehsan Barkhordar

como se dijo en organización de Python:

clase escribiendo.Dict(dict, MutableMapping[KT, VT])

Una versión genérica de dict. Útil para anotar tipos de devolución. Para anotar argumentos, se prefiere utilizar un tipo de colección abstracta como Mapping.

Este tipo se puede utilizar de la siguiente manera:

def count_words(text: str) -> Dict[str, int]:
    ...

Pero dict es menos general y podrá alterar el mapeo pasado. De hecho, en python.Dict especificas mas detalles.

Otro consejo:

En desuso desde la versión 3.9: builtins.dict ahora admite []. Ver PEP 585
y tipo de alias genérico.

  • Muy bueno señalar la desaprobación de typing.Dict.

    – jrc

    21 de junio a las 20:22

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad