¿Por qué es tan lenta la función ‘todo’ de Python?

He escrito algunas pruebas muy simples (lo sé, no son “concluyentes”, pero me dan curiosidad). Corrí con la optimización y todo ese jazz.

from time import time alist = [ 2, 4, 6, 8, 10, 12, 24, 48, 64, 128 ] def all_even( alist ): for val in alist: if not (val & 1) == 0: return False return True def all_even_bad( alist ): result = False for val in alist: if not (val & 1) == 0: result = False else: result = True return result def main(): start = time() for i in range(1, 10000): all_even( alist ) print('All even: {0}'.format(time() - start)) start = time() for i in range(1, 10000): all_even_bad( alist ) print('All even bad: {0}'.format(time() - start)) start = time() for i in range(1, 10000): all( val & 1 == 0 for val in alist ) print('All one: {0}'.format(time() - start)) if __name__ == '__main__': main() 

Obtengo resultados en torno a:

 > All even: 2.86299991608 > All even bad: 3.71399998665 > All one: 3.89900016785 

Parece que la función incorporada no se rescata temprano?

definitivamente all() sale temprano, creo que la diferencia de comportamiento es solo el resultado de la sobrecarga requerida para crear el generador.

Aquí hay una prueba de que all() sale antes:

 In [8]: alist = [3] + [0] * 2**20 # alist bigger, with an early odd In [10]: %timeit all_even(alist) 1000000 loops, best of 3: 309 ns per loop In [11]: %timeit all_even_bad(alist) 10 loops, best of 3: 133 ms per loop In [12]: %timeit all(val & 1 == 0 for val in alist) 1000000 loops, best of 3: 891 ns per loop 

Tenga en cuenta que aunque all() es más lento que all_even() aquí, todavía es significativamente más rápido que la versión de la función que no sale antes.

No tiene elementos que no pasen la prueba, por lo tanto, no hay forma de cortocircuito.

Ya que todos los números en su lista son de hecho parejos, ¿no podría lógicamente rescatarse temprano? La sobrecarga de su llamada all() puede provenir de la construcción de un objeto generator .