tipos propias procedimientos otra matematicas llamar lista funciones funcion dentro definir python function parameters

propias - Tipos de parámetros de función en Python



llamar funciones dentro de funciones python (11)

A Python no le importa lo que le pase a sus funciones. Cuando llame a my_func(a,b) , las variables param1 y param2 contendrán los valores de a y b. Python no sabe que está llamando a la función con los tipos adecuados, y espera que el programador se encargue de eso. Si su función se llamará con diferentes tipos de parámetros, puede ajustar el código accediendo a ellos con try / except blocks y evaluar los parámetros de la forma que desee.

A menos que me equivoque, crear una función en Python funciona así:

def my_func(param1, param2): # stuff

Sin embargo, en realidad no das los tipos de esos parámetros. Además, si mal no recuerdo, Python es un lenguaje fuertemente tipado, por lo que parece que Python no debería permitirle pasar un parámetro de un tipo diferente al esperado por el creador de la función. Sin embargo, ¿cómo sabe Python que el usuario de la función está pasando los tipos adecuados? ¿El programa simplemente morirá si es del tipo incorrecto, suponiendo que la función realmente usa el parámetro? ¿Tienes que especificar el tipo?


Como explica Alex Martelli ,

La solución normal, Pythonic, preferida es casi invariablemente "tipa pato": intente utilizar el argumento como si fuera de un cierto tipo deseado, hágalo en una declaración try / except que capture todas las excepciones que podrían surgir si el argumento no fuera de hecho de ese tipo (o de cualquier otro tipo que simule bien a pato ;-), y en la cláusula except, intente con otra cosa (usando el argumento "como si" fuera de algún otro tipo).

Lee el resto de su publicación para obtener información útil.


En Python todo tiene un tipo. Una función de Python hará todo lo que se le pida si el tipo de argumentos lo admite.

Ejemplo: foo agregará todo lo que se puede __add__ ed;) sin preocuparse demasiado por su tipo. Entonces eso significa, para evitar fallas, deberías proporcionar solo aquellas cosas que soportan la suma.

def foo(a,b): return a + b class Bar(object): pass class Zoo(object): def __add__(self, other): return ''zoom'' if __name__==''__main__'': print foo(1, 2) print foo(''james'', ''bond'') print foo(Zoo(), Zoo()) print foo(Bar(), Bar()) # Should fail


Hay una excepción notoria de la mecanografía de patos que vale la pena mencionar en esta página.

Cuando la función str llama al método de clase __str__ , comprueba sutilmente su tipo:

>>> class A(object): ... def __str__(self): ... return ''a'',''b'' ... >>> a = A() >>> print a.__str__() (''a'', ''b'') >>> print str(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __str__ returned non-string (type tuple)

Como si Guido nos dijera qué excepción debería hacer un programa si encuentra un tipo inesperado.


Las otras respuestas han hecho un buen trabajo al explicar la tipificación de pato y la respuesta simple por tzot :

Python no tiene variables, como otros lenguajes donde las variables tienen un tipo y un valor; tiene nombres que apuntan a objetos, que conocen su tipo.

Sin embargo , una cosa interesante ha cambiado desde 2010 (cuando se hizo la pregunta por primera vez), es decir, la implementación de PEP 3107 (implementado en Python 3). Ahora puede especificar el tipo de parámetro y el tipo de retorno de una función como esta:

def pick(l: list, index: int) -> int: return l[index]

Aquí podemos ver que pick toma 2 parámetros, una lista l y un index entero. También debería devolver un número entero.

Entonces aquí está implícito que l es una lista de enteros que podemos ver sin mucho esfuerzo, pero para funciones más complejas puede ser un poco confuso en cuanto a lo que la lista debe contener. También queremos que el valor predeterminado del index sea ​​0. Para resolver esto, puede elegir escribir pick como este en su lugar:

def pick(l: "list of ints", index: int = 0) -> int: return l[index]

Tenga en cuenta que ahora ponemos una cadena como el tipo de l , que está sintácticamente permitido, pero no es bueno para analizar mediante programación (lo cual volveremos más adelante).

Es importante tener en cuenta que Python no generará un TypeError si pasa un float al index , la razón de esto es uno de los puntos principales en la filosofía de diseño de Python: "Aquí todos estamos de acuerdo con los adultos" , lo que significa que usted está se espera que esté al tanto de lo que puede pasar a una función y lo que no puede. Si realmente desea escribir código que arroje TypeErrors, puede usar la función isinstance para verificar que el argumento pasado sea del tipo apropiado o una subclase de este modo:

def pick(l: list, index: int = 0) -> int: if not isinstance(l, list): raise TypeError return l[index]

En la siguiente sección y en los comentarios, se explica más acerca de por qué raramente debe hacer esto y qué debe hacer en su lugar.

PEP 3107 no solo mejora la legibilidad del código, sino que también cuenta con varios casos de uso adecuados que puede leer here .

La anotación de tipo recibió mucha más atención en Python 3.5 con la introducción de PEP 484 que presenta un módulo estándar para sugerencias de tipo.

Esta sintaxis viene de la herramienta de comprobación de tipo estático opcional mypy ( GitHub ) que está en desarrollo (y compatible con PEP 484 ).

Con el módulo de tipeo viene una colección bastante completa de sugerencias tipo, que incluyen:

  • List , Tuple , Set , Map - para list , tuple , set y map respectivamente.
  • Iterable : útil para generadores.
  • Any , cuando podría ser cualquier cosa.
  • Union : cuando podría ser cualquier cosa dentro de un conjunto específico de tipos, en oposición a Any .
  • Optional , cuando podría ser Ninguno. Taquigrafía para Union[T, None] .
  • TypeVar : se usa con genéricos.
  • Callable : se usa principalmente para funciones, pero podría usarse para otros callables.

Esta lista representa los consejos de tipo más comunes, pero está lejos de ser exhaustiva. Se puede encontrar una lista completa en la documentación del módulo de escritura .

Aquí está el ejemplo anterior usando los métodos de anotación introducidos en el módulo de tipeo:

from typing import List def pick(l: List[int], index: int) -> int: return l[index]

Una característica poderosa es el Callable que le permite escribir métodos de anotación que toman una función como argumento. Por ejemplo:

from typing import Callable, Any, Iterable def imap(f: Callable[[Any], Any], l: Iterable[Any]) -> List[Any]: """An immediate version of map, don''t pass it any infinite iterables!""" return list(map(f, l))

El ejemplo anterior podría ser más preciso con el uso de TypeVar lugar de Any , pero esto se dejó como un ejercicio para el lector, ya que creo que ya he llenado mi respuesta con demasiada información sobre las maravillosas características nuevas habilitadas por el tipo de alusión .

Anteriormente, cuando se documentaba el código Python con, por ejemplo, Sphinx algunas de las funcionalidades anteriores se podían obtener escribiendo docstrings con el siguiente formato:

def pick(l, index): """ :param l: list of integers :type l: list :param index: index at which to pick an integer from *l* :type index: int :returns: integer at *index* in *l* :rtype: int """ return l[index]

Como puede ver, esto requiere una serie de líneas adicionales (el número exacto depende de qué tan explícito desee y cómo formatee su docstring). Pero ahora debe quedar claro para usted cómo PEP 3107 proporciona una alternativa que es en muchas (todas) formas superiores. Esto es especialmente cierto en combinación con PEP 484 que, como hemos visto, proporciona un módulo estándar que define una sintaxis para estas sugerencias / anotaciones de tipo que se pueden usar de forma tal que es inequívoco y preciso pero flexible, lo que lo convierte en un combinación poderosa

En mi opinión personal, esta es una de las mejores características de Python. No puedo esperar a que la gente comience a aprovechar su poder. Perdón por la respuesta larga, pero esto es lo que sucede cuando me emociono.

here se puede encontrar un ejemplo de código Python que usa mucho tipo de sugerencias.


Muchos idiomas tienen variables, que son de un tipo específico y tienen un valor. Python no tiene variables; tiene objetos y usa nombres para referirse a estos objetos.

En otros idiomas, cuando dices:

a = 1

luego una variable (típicamente entera) cambia su contenido al valor 1.

En Python,

a = 1

significa "usar el nombre a para referirse al objeto 1 ". Puede hacer lo siguiente en una sesión interactiva de Python:

>>> type(1) <type ''int''>

El type función se llama con el objeto 1 ; dado que cada objeto conoce su tipo, es fácil para el type averiguar dicho tipo y devolverlo.

Del mismo modo, cada vez que define una función

def funcname(param1, param2):

la función recibe dos objetos y los nombra param1 y param2 , independientemente de sus tipos. Si desea asegurarse de que los objetos recibidos sean de un tipo específico, codifique su función como si fueran del tipo o tipos necesarios y capte las excepciones que se lanzan si no lo son. Las excepciones lanzadas suelen ser TypeError (se utilizó una operación no válida) y AttributeError (se intentó acceder a un miembro inexistente (los métodos también son miembros)).


No especifica un tipo. El método solo fallará (en tiempo de ejecución) si intenta acceder a atributos que no están definidos en los parámetros que se pasan.

Entonces esta simple función:

def no_op(param1, param2): pass

... no fallará sin importar qué dos args se pasen.

Sin embargo, esta función:

def call_quack(param1, param2): param1.quack() param2.quack()

... fallará en el tiempo de ejecución si los param1 y param2 no tienen ambos atributos llamados quack .


No vi esto mencionado en otras respuestas, así que lo agregaré al bote.

Como han dicho otros, Python no impone el tipo de función ni los parámetros del método. Se supone que usted sabe lo que está haciendo, y que si realmente necesita saber el tipo de algo que se transfirió, lo comprobará y decidirá qué hacer por usted mismo.

Una de las herramientas principales para hacer esto es la función isinstance ().

Por ejemplo, si escribo un método que espera obtener datos de texto binario en bruto, en lugar de las cadenas codificadas para utf-8 normales, podría verificar el tipo de parámetros en el camino y adaptarme a lo que encuentro, o plantear una excepción a rechazar.

def process(data): if not isinstance(data, bytes) and not isinstance(data, bytearray): raise TypeError(''Invalid type: data must be a byte string or bytearray, not %r'' % type(data)) # Do more stuff

Python también proporciona todo tipo de herramientas para cavar en objetos. Si eres valiente, incluso puedes usar importlib para crear tus propios objetos de clases arbitrarias, sobre la marcha. Hice esto para recrear objetos a partir de datos JSON. Tal cosa sería una pesadilla en un lenguaje estático como C ++.


Nunca especificas el tipo; Python tiene el concepto de tipado de pato ; Básicamente, el código que procesa los parámetros hará ciertas suposiciones sobre ellos, tal vez llamando a ciertos métodos que se espera que implemente un parámetro. Si el parámetro es del tipo incorrecto, se lanzará una excepción.

En general, depende de su código asegurarse de que está pasando por los objetos del tipo correcto; no existe un compilador que lo haga cumplir por adelantado.


Python está fuertemente tipado porque cada objeto tiene un tipo, cada objeto conoce su tipo, es imposible usar accidentalmente o deliberadamente un objeto de un tipo "como si" fuera un objeto de un tipo diferente , y todas las operaciones elementales del objeto son delegado a su tipo.

Esto no tiene nada que ver con los nombres . Un nombre en Python no "tiene un tipo": si y cuando se define un nombre, el nombre se refiere a un objeto , y el objeto tiene un tipo (pero eso de hecho no fuerza un tipo sobre el nombre : a nombre es un nombre).

Un nombre en Python puede perfectamente referirse a diferentes objetos en diferentes momentos (como en la mayoría de los lenguajes de programación, aunque no en todos), y no hay restricción en el nombre tal que, si alguna vez se refirió a un objeto de tipo X, entonces está forzosamente limitado a referirse solo a otros objetos de tipo X. Las restricciones en los nombres no son parte del concepto de "tipado fuerte", aunque algunos entusiastas de tipado estático (donde los nombres se restringen, y en una compilación AKA estática, tiempo, moda, también) abusan del término de esta manera.


Python no está fuertemente tipado en el sentido de comprobación de tipos estáticos o en tiempo de compilación.

La mayoría de los códigos de Python corresponden a la llamada "Duck Typing" , por ejemplo, si buscas un método de read en un objeto, no te importa si el objeto es un archivo en un disco o un socket, solo quieres leer N bytes desde allí.