pasar - ¿Python optimiza una variable que solo se usa como valor de retorno?
lista de funciones de python (2)
¿Hay alguna diferencia final entre los siguientes dos fragmentos de código? El primero asigna un valor a una variable en una función y luego devuelve esa variable. La segunda función solo devuelve el valor directamente.
¿Python los convierte en bytecode equivalentes? ¿Uno de ellos es más rápido?
Caso 1 :
def func():
a = 42
return a
Caso 2 :
def func():
return 42
Ambos son básicamente lo mismo, excepto que en el primer caso el objeto
42
simplemente se asigna a una variable llamada
a
o, en otras palabras, los nombres (es decir,
a
) se refieren a valores (es decir,
42
).
No realiza ninguna tarea técnicamente, en el sentido de que nunca copia ningún dato.
Mientras se
return
, este enlace denominado
a
se devuelve en el primer caso mientras que el objeto
42
se devuelve en el segundo caso.
Para más información, consulte este gran artículo de Ned Batchelder
No lo hace
La compilación del código de byte de CPython solo se pasa a través de un pequeño optimizador de mirilla diseñado para realizar solo optimizaciones básicas (consulte test_peepholer.py en el conjunto de pruebas para obtener más información sobre estas optimizaciones).
Para ver lo que realmente va a suceder, use
dis
* para ver las instrucciones generadas.
Para la primera función, que contiene la asignación:
from dis import dis
dis(func)
2 0 LOAD_CONST 1 (42)
2 STORE_FAST 0 (a)
3 4 LOAD_FAST 0 (a)
6 RETURN_VALUE
Mientras, para la segunda función:
dis(func2)
2 0 LOAD_CONST 1 (42)
2 RETURN_VALUE
Dos instrucciones más (rápidas) se utilizan en la primera:
STORE_FAST
y
LOAD_FAST
.
Estos hacen un almacenamiento rápido y
fastlocals
el valor en la matriz
fastlocals
del marco de ejecución actual.
Luego, en ambos casos, se realiza un
RETURN_VALUE
.
Entonces, el segundo es
ligeramente
más rápido debido a que se necesitan menos comandos para ejecutar.
En general, tenga en cuenta que el compilador CPython es conservador en las optimizaciones que realiza. No es ni intenta ser tan inteligente como otros compiladores (que, en general, también tienen mucha más información para trabajar). El objetivo principal del diseño, además de ser obviamente correcto, es a) mantenerlo simple yb) ser lo más rápido posible al compilarlos para que ni siquiera note que existe una fase de compilación.
Al final, no deberías molestarte con pequeños problemas como este. El beneficio en velocidad es pequeño, constante y, eclipsado por la sobrecarga introducida por el hecho de que Python se interpreta.
*
dis
es un pequeño módulo de Python que desarma su código, puede usarlo para ver el código de bytes de Python que ejecutará la VM.
Nota: Como también se indicó en un comentario de @Jorn Vernee, esto es específico de la implementación de Python en CPython. Otras implementaciones podrían hacer optimizaciones más agresivas si así lo desean, CPython no lo hace.