tipos - ejemplos de try catch en python
Desempaquetar argumentos: solo los argumentos con nombre pueden seguir*expresión (6)
Lo siguiente funciona maravillosamente en Python:
def f(x,y,z): return [x,y,z]
a=[1,2]
f(3,*a)
Los elementos de a
se desempaquetan como si lo f(3,1,2)
llamado f(3,1,2)
y devuelve [3,1,2]
. ¡Maravilloso!
Pero no puedo descomprimir los elementos de a
en los primeros dos argumentos:
f(*a,3)
En lugar de llamar a eso como f(1,2,3)
, obtengo "SyntaxError: solo los argumentos con nombre pueden seguir * expresión".
Me pregunto por qué tiene que ser así y si hay algún truco inteligente del que pueda no estar al tanto para desempaquetar arreglos en partes arbitrarias de listas de argumentos sin recurrir a variables temporales.
Bonito. Esto también funciona para tuplas. No olvides la coma:
a = (1,2)
f(*(a+(3,)))
Como señala la respuesta de Raymond Hettinger, esto puede cambiar en Python 3 y aquí hay una propuesta relacionada , que ha sido aceptada. Especialmente relacionado con la pregunta actual, este es uno de los posibles cambios a esa propuesta que se discutió:
Solo permite una expresión con estrella como el último elemento en la lista de reproducción exprés. Esto simplificaría un poco el código de desempaquetado y permitiría asignar un iterador a la expresión con estrella. Este comportamiento fue rechazado porque sería demasiado sorprendente.
Entonces hay razones de implementación para la restricción con los argumentos de la función de desembalaje, ¡pero de hecho es un poco sorprendente!
Mientras tanto, esta es la solución que estaba buscando, algo obvio en retrospectiva:
f(*(a+[3]))
Gracias al PEP 448 - Generalizaciones adicionales de desembalaje ,
f(*a, 3)
Ahora se acepta la sintaxis a partir de Python 3.5 . Del mismo modo, puede utilizar el argumento de doble estrella **
para palabras clave desempaquetado en cualquier lugar y cualquiera de los dos se puede usar varias veces.
No tiene por qué ser así. Era solo una regla que Guido descubrió que era sensato.
En Python 3, las reglas para desempaquetar se han liberalizado un poco:
>>> a, *b, c = range(10)
>>> a
0
>>> b
[1, 2, 3, 4, 5, 6, 7, 8]
>>> c
9
Dependiendo de si Guido considera que mejoraría el lenguaje, esa liberalización también podría extenderse a los argumentos de la función.
Vea la discusión sobre desempaquetado iterativo extendido para algunas reflexiones sobre por qué Python 3 cambió las reglas.
Puede usar f(*a, z=3)
si usa f(*a, 3)
, no sabe cómo desempaquetar el parámetro, ya que proporcionó 2 parámetros y 2 es el segundo.
f
espera 3 argumentos ( x
, y
, z
, en ese orden).
Supongamos que L = [1,2]
. Cuando llamas a f(3, *L)
, lo que hace python detrás de las escenas, es llamar a f(3, 1, 2)
, sin saber realmente la longitud de L
Entonces, ¿qué sucede si L
fue en cambio [1,2,3]
?
Luego, cuando llame a f(3, *L)
, terminará llamando a f(3,1,2,3)
, lo cual será un error porque f
espera exactamente 3 argumentos y usted le dio 4.
Ahora, supongamos L=[1,2]1. Look at what happens when you call
L=[1,2]1. Look at what happens when you call
f`:
>>> f(3,*L) # works fine
>>> f(*L) # will give you an error when f(1,2) is called; insufficient arguments
Ahora, usted sabe implícitamente cuando llama a f(*L, 3)
que 3 serán asignados a z
, pero Python no lo sabe. Solo sabe que los últimos j
muchos elementos de la entrada a f
se definirán por los contenidos de L
Pero dado que no conoce el valor de len(L)
, no puede hacer suposiciones sobre si f(*L,3)
tendría la cantidad correcta de argumentos.
Sin embargo, este no es el caso con f(3,*L)
. En este caso, Python sabe que todos los argumentos, EXCEPTO el primero, estarán definidos por el contenido de L
Pero si ha nombrado argumentos f(x=1, y=2, z=3)
, entonces los argumentos asignados por nombre se vincularán primero. Solo entonces están vinculados los argumentos posicionales. Entonces haces f(*L, z=3)
. En ese caso, z
está obligado a 3
primero, y luego, los otros valores se unen.
Ahora, curiosamente, si hicieras f(*L, y=3)
, eso te daría un error al tratar de asignar a y
dos veces (una vez con la palabra clave, una vez más con el posicional)
Espero que esto ayude