poner - ¿Es seguro confiar en el orden de evaluación de los argumentos de la función de Python?
python y django tutorial (2)
Citando de la documentación de referencia :
Python evalúa expresiones de izquierda a derecha.
Entonces sí, puedes contar con eso (con una excepción, mira abajo).
Una llamada (la parte (...)
después de una primaria, como el nombre de una función) es simplemente otra expresión primaria , y los argumentos para la llamada son solo más expresiones.
Nota : hay una excepción a esta regla. Cuando se usa *expression
en una llamada (para expandir un iterable para formar argumentos posicionales adicionales), esta expresión se evalúa antes de cualquier expresión de argumento de palabra clave :
>>> from itertools import count
>>> def bar(n, r=(), c=count()): print(f''{next(c)}: bar({n!r})''); return r
...
>>> def foo(*args, **kwargs): pass
...
>>> foo(bar(''a1''), spam=bar(''a2''), *bar(''varargs''), **bar(''kwargs'', {}))
0: bar(''a1'')
1: bar(''varargs'')
2: bar(''a2'')
3: bar(''kwargs'')
La documentación vinculada dice:
Una consecuencia de esto es que, aunque la sintaxis
*expression
puede aparecer después de los argumentos explícitos de palabras clave, se procesa antes de los argumentos de la palabra clave [.]
Esta pregunta ya tiene una respuesta aquí:
¿Es seguro suponer que los argumentos de la función se evalúan de izquierda a derecha en Python?
La referencia indica que sucede de esa manera, pero tal vez haya alguna forma de cambiar este orden que puede romper mi código.
Lo que quiero hacer es agregar un sello de tiempo para la llamada a la función:
l = []
l.append(f(), time.time())
Entiendo que puedo evaluar los argumentos secuencialmente:
l = []
res = f()
t = time.time()
l.append(res, t)
Pero parece menos elegante, así que preferiría la primera manera si puedo confiar en ello.
Sí, Python siempre evalúa los argumentos de la función de izquierda a derecha.
Esto va para cualquier lista separada por comas por lo que sé:
>>> from __future__ import print_function
>>> def f(x, y): pass
...
>>> f(print(1), print(2))
1
2
>>> [print(1), print(2)]
1
2
[None, None]
>>> {1:print(1), 2:print(2)}
1
2
{1: None, 2: None}
>>> def f(x=print(1), y=print(2)): pass
...
1
2