¿Cómo saber el tipo de retorno de la función y los tipos de argumento?

84

Si bien soy consciente del concepto de escritura de pato de Python, a veces tengo problemas con el tipo de argumentos de las funciones o el tipo de valor de retorno de la función.

Ahora, si escribí la función yo mismo, SÍ conozco los tipos. Pero, ¿qué pasa si alguien quiere usar y llamar a mis funciones, cómo se espera que conozca los tipos? Por lo general, pongo información de tipo en la cadena de documentos de la función (como: "...the id argument should be an integer..."y "... the function will return a (string, [integer]) tuple.")

Pero, ¿buscar la información en la cadena de documentos (y ponerla allí, como codificador) es realmente la forma en que se supone que debe hacerse?

Editar: Si bien la mayoría de las respuestas parecen dirigirse hacia "¡sí, documento!" Siento que esto no siempre es muy fácil para los tipos "complejos".
Por ejemplo: ¿cómo describir de manera concisa en una cadena de documentos que una función devuelve una lista de tuplas, con cada tupla del formulario (node_id, node_name, uptime_minutes) y que los elementos son respectivamente una cadena, una cadena y un entero?
La documentación de la cadena de documentos PEP no da ninguna guía al respecto.
Supongo que el contraargumento será que en ese caso se deberían usar clases, pero creo que Python es muy flexible porque permite pasar estas cosas usando listas y tuplas, es decir, sin clases.

Rabarberski
fuente
2
La respuesta corta es sí". La respuesta larga es "sí, por supuesto". No sé si ha mirado mucho código Python, pero probablemente debería actualizar la pregunta para indicar qué paquetes usa realmente para que podamos dirigirlo al código que puede leer para ver cómo se hacen las cosas en el código de la biblioteca. que estás usando ahora mismo.
S.Lott
@ S.Lott: Actualmente estoy luchando con el paquete de mecanizar, pero supongo que está (desafortunadamente) mal documentado.
Rabarberski
4
Python es genial porque puedes escribir mucho código rápidamente y no tienes que preocuparte por cosas mundanas como tipos de retorno, tipos de argumentos, rendimiento en tiempo de ejecución, personas que tienen que usar y mantener tu código espagueti durante los próximos 10 años, etc. Suspiro .
jarmod

Respuestas:

120

Bueno, ¡las cosas han cambiado un poco desde 2011! Ahora hay sugerencias de tipo en Python 3.5 que puede usar para anotar argumentos y devolver el tipo de su función. Por ejemplo esto:

def greeting(name):
  return 'Hello, {}'.format(name)

ahora se puede escribir así:

def greeting(name: str) -> str:
  return 'Hello, {}'.format(name)

Como ahora puede ver los tipos, hay algún tipo de verificación de tipo estático opcional que lo ayudará a usted y a su verificador de tipo a investigar su código.

para obtener más explicaciones, sugiero que eche un vistazo a la publicación del blog sobre sugerencias de tipo en el blog de PyCharm .

Rsh
fuente
Tenga en cuenta que también se sugirió una sintaxis de sugerencia de tipo para Python 2.7 aquí en el mismo PEP-0484. Y funciona en PyCharm, al menos desde la versión 2017.3.
viddik13
1
Si la función de saludo con exactamente la misma definición devuelve un objeto de tipo int, no surgirá ningún error. Entonces, ¿cuál es el uso de este tipo de verificación de tipos si menciona el tipo de retorno explícitamente, pero no obedece la regla y devuelve un tipo de objeto diferente?
Arashsyh
2
@Arashsyh: Sí, tiene razón, la sugerencia de tipo no convierte a Python en un lenguaje escrito estáticamente, depende de usted usar los tipos correctos de la manera correcta. Y esos tipos de sugerencias lo ayudan a desarrollar más rápido, autodocumentar su código o recibir una advertencia cuando se estropea algo. Especialmente cuando usa PyCharm (o un IDE similar), le advertirá en caso de que use un tipo diferente y le ayudará con algunas otras cosas. Recomiendo leer la publicación del blog sugerida en la respuesta anterior.
Nerxis
¿Es esto más rápido computacionalmente?
Bryce Wayne
17

Así es como funcionan los lenguajes dinámicos. Sin embargo, no siempre es algo bueno, especialmente si la documentación es deficiente: ¿alguien intentó usar un marco de Python mal documentado? A veces tienes que volver a leer la fuente.

Aquí hay algunas estrategias para evitar problemas con la escritura de pato:

  • crea un idioma para tu dominio problemático
  • esto te ayudará a nombrar las cosas correctamente
  • utilizar tipos para representar conceptos en el idioma de su dominio
  • Parámetros de función de nombre usando el vocabulario del idioma del dominio

Además, uno de los puntos más importantes:

  • ¡Mantenga los datos lo más locales posible!

Solo deberían transmitirse unos pocos tipos bien definidos y documentados. Cualquier otra cosa debería ser obvia al mirar el código: no tenga tipos de parámetros extraños provenientes de muy lejos que no pueda descifrar mirando en las cercanías del código ...

Relacionado (y también relacionado con cadenas de documentos), hay una técnica en Python llamada doctests. Úselo para documentar cómo se espera que se usen sus métodos, ¡y tenga una buena cobertura de prueba unitaria al mismo tiempo!

Daren Thomas
fuente
1
La documentación de Numpy es un buen ejemplo representativo de la filosofía establecida en la respuesta anterior.
Jerry
5

Sí, debe usar cadenas de documentación para hacer que sus clases y funciones sean más amigables para otros programadores:

Más: http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring

Algunos editores le permiten ver cadenas de documentos mientras escribe, por lo que realmente facilita el trabajo.

Maciej Ziarko
fuente
+1: documentarlo, es la única forma sensata, y ese también es el caso de los idiomas escritos estáticamente. Los tipos de devolución son una fracción insignificante de la imagen completa.
detly
Me gustan mis tipos muchas gracias. Documentación + tipos = cielo
masm64
5

Asistí a un curso de Coursera, hubo una lección en la que nos enseñaron sobre la receta de diseño.

Debajo del formato de cadena de documentos, encontré a Preety útil.

def area (base, altura):
    '' '(número, número) -> número # ** TipoContrato **
    Devuelve el área de un tring con dimensiones base # ** Descripción **
    y altura

    >>> área (10,5) # ** Ejemplo **
    25,0
    >> área (2.5,3)
    3,75
    '' '
    return (base * altura) / 2 

Creo que si las cadenas de documentos se escriben de esta manera, podría ayudar mucho a los desarrolladores.

Enlace al video [Ver el video] : https://www.youtube.com/watch?v=QAPg6Vb_LgI

Sumit Murari
fuente
2

Sí lo es.

En Python, una función no siempre tiene que devolver una variable del mismo tipo (aunque su código será más legible si sus funciones siempre devuelven el mismo tipo). Eso significa que no puede especificar un solo tipo de retorno para la función.

Del mismo modo, los parámetros no siempre tienen que ser del mismo tipo.

thomson_matt
fuente
1

Por ejemplo: ¿cómo describir de manera concisa en una cadena de documentos que una función devuelve una lista de tuplas, con cada tupla del formulario (node_id, node_name, uptime_minutes) y que los elementos son respectivamente una cadena, una cadena y un entero?

Um ... No hay una descripción "concisa" de esto. Es complejo. Lo ha diseñado para que sea complejo. Y requiere documentación compleja en la cadena de documentos.

Lo siento, pero la complejidad es ... bueno, compleja.

S. Lot
fuente
2
OKAY. Fuera del tema (más o menos): pero ¿qué sería entonces un diseño más limpio? Clases
Rabarberski
@Rabarberski: No necesariamente. La complejidad suena inevitable aquí. La concisión no siempre es alcanzable o incluso deseable.
S.Lott
Una forma obvia de documentar este tipo de cosas es usando algo similar a los genéricos de Java, como en: list <tuple <int, str, int >>. Pero esa no es la forma de Python, para bien o para mal.
skyler
0

Sí, ya que es un lenguaje de tipo dinámico;)

Lea esto como referencia: PEP 257

Alois Cochard
fuente
0

Docstrings (y documentación en general). Python 3 introduce anotaciones de funciones (opcionales), como se describe en PEP 3107 (pero no omita las cadenas de documentos)

Steven
fuente