O objetivo foi mostrar a diferença de desempenho das duas formas de fazer a mesma coisa.
Nesse primeiro caso, usando um array numpy:
%time for _ in range(100): np_array *= 2
A cada interação, ele multiplica todos os valores por 2 de uma só vez.
No segundo caso, usando list comprehension:
%time for _ in range(100): py_list = [x * 2 for x in py_list]
Tem que fazer um por um, vai ter que multiplicar por 2 cada um dos elementos do array, ou seja, vai ter que fazer essa multiplicação por 2 um milhão de vezes.
Já imaginou ter que fazer isso 100 vezes?
Espero ter ajudado.
Abç,
Jefferson