ventajas tutorial sirve que para español desventajas desde curso cero caracteristicas python performance python-2.7 python-3.x cpython

sirve - tutorial python desde cero



¿Por qué Python 3 es considerablemente más lento que Python 2? (1)

Esta pregunta ya tiene una respuesta aquí:

He estado tratando de entender por qué Python 3 realmente toma mucho tiempo comparado con Python 2 en ciertas situaciones, a continuación se muestran algunos casos que he verificado de python 3.4 a python 2.7.

Nota: He revisado algunas de las preguntas como ¿Por qué no hay función xrange en Python3? y bucle en python3 mucho más lento que python2 y el mismo código más lento en Python3 en comparación con Python2 , pero creo que no entendí el motivo real de este problema.

He intentado esta pieza de código para mostrar cómo está haciendo la diferencia:

MAX_NUM = 3*10**7 # This is to make compatible with py3.4. try: xrange except: xrange = range def foo(): i = MAX_NUM while i> 0: i -= 1 def foo_for(): for i in xrange(MAX_NUM): pass

Cuando intenté ejecutar este programa con py3.4 y py2.7 obtuve los siguientes resultados.

Nota: Estas estadísticas llegaron a través de una máquina de 64 bit con 2.6Ghz procesador de 2.6Ghz y calcularon el tiempo usando time.time() en un solo ciclo.

Output : Python 3.4 ----------------- 2.6392083168029785 0.9724123477935791 Output: Python 2.7 ------------------ 1.5131521225 0.475143909454

Realmente no creo que se hayan aplicado cambios a while o xrange de 2.7 a 3.4, sé que el range ha comenzado a actuar como xrange en py3.4, pero como dice la documentación

range() ahora se comporta como xrange() usado para comportarse, excepto que funciona con valores de tamaño arbitrario. El último ya no existe.

esto significa que el cambio de xrange a range es muy similar a un cambio de nombre pero funciona con valores arbitrarios.

También he verificado el código de bytes desensamblado.

A continuación se muestra el código de byte desmontado para la función foo() :

Python 3.4: --------------- 13 0 LOAD_GLOBAL 0 (MAX_NUM) 3 STORE_FAST 0 (i) 14 6 SETUP_LOOP 26 (to 35) >> 9 LOAD_FAST 0 (i) 12 LOAD_CONST 1 (0) 15 COMPARE_OP 4 (>) 18 POP_JUMP_IF_FALSE 34 15 21 LOAD_FAST 0 (i) 24 LOAD_CONST 2 (1) 27 INPLACE_SUBTRACT 28 STORE_FAST 0 (i) 31 JUMP_ABSOLUTE 9 >> 34 POP_BLOCK >> 35 LOAD_CONST 0 (None) 38 RETURN_VALUE python 2.7 ------------- 13 0 LOAD_GLOBAL 0 (MAX_NUM) 3 STORE_FAST 0 (i) 14 6 SETUP_LOOP 26 (to 35) >> 9 LOAD_FAST 0 (i) 12 LOAD_CONST 1 (0) 15 COMPARE_OP 4 (>) 18 POP_JUMP_IF_FALSE 34 15 21 LOAD_FAST 0 (i) 24 LOAD_CONST 2 (1) 27 INPLACE_SUBTRACT 28 STORE_FAST 0 (i) 31 JUMP_ABSOLUTE 9 >> 34 POP_BLOCK >> 35 LOAD_CONST 0 (None) 38 RETURN_VALUE

Y debajo está el código de byte desensamblado para la función foo_for() :

Python: 3.4 19 0 SETUP_LOOP 20 (to 23) 3 LOAD_GLOBAL 0 (xrange) 6 LOAD_GLOBAL 1 (MAX_NUM) 9 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 12 GET_ITER >> 13 FOR_ITER 6 (to 22) 16 STORE_FAST 0 (i) 20 19 JUMP_ABSOLUTE 13 >> 22 POP_BLOCK >> 23 LOAD_CONST 0 (None) 26 RETURN_VALUE Python: 2.7 ------------- 19 0 SETUP_LOOP 20 (to 23) 3 LOAD_GLOBAL 0 (xrange) 6 LOAD_GLOBAL 1 (MAX_NUM) 9 CALL_FUNCTION 1 12 GET_ITER >> 13 FOR_ITER 6 (to 22) 16 STORE_FAST 0 (i) 20 19 JUMP_ABSOLUTE 13 >> 22 POP_BLOCK >> 23 LOAD_CONST 0 (None) 26 RETURN_VALUE

Si comparamos ambos códigos de bytes, han producido el mismo código de bytes desmontados.

Ahora me pregunto qué cambio de 2.7 a 3.4 realmente está causando este gran cambio en el tiempo de ejecución en el fragmento de código dado.


La diferencia está en la implementación del tipo int . Python 3.x utiliza el tipo de entero de tamaño arbitrario ( long en 2.x) exclusivamente, mientras que en Python 2.x para valores de hasta sys.maxint se usa un tipo de int más simple que utiliza una C long simple bajo el capó.

Una vez que limites tus loops a enteros long , Python 3.x es más rápido:

>>> from timeit import timeit >>> MAX_NUM = 3*10**3 >>> def bar(): ... i = MAX_NUM + sys.maxsize ... while i > sys.maxsize: ... i -= 1 ...

Python 2:

>>> timeit(bar, number=10000) 5.704327821731567

Python 3:

>>> timeit(bar, number=10000) 3.7299320790334605

sys.maxsize porque sys.maxint se eliminó de Python 3, pero el valor entero es básicamente el mismo.

La diferencia de velocidad en Python 2 se limita así al primer (2 ** 63) - 1 enteros en 64 bits, (2 ** 31) - 1 enteros en sistemas de 32 bits.

Como no puede usar el tipo long con xrange() en Python 2, no xrange() una comparación para esa función.