作者:Nirmalya Ghosh 来源:deephub 转自:数据STUDIO
在本文中,我将介绍一些简单的方法,可以将Python for循环的速度提高1.3到900倍。
Python内建的一个常用功能是timeit模块。下面几节中我们将使用它来度量循环的当前性能和改进后的性能。
对于每种方法,我们通过运行测试来建立基线,该测试包括在10次测试运行中运行被测函数100K次(循环),然后计算每个循环的平均时间(以纳秒为单位,ns)。
几个简单方法
1、列表推导式
# Baseline version (Inefficient way)
# Calculating the power of numbers
# Without using List Comprehension
def test_01_v0(numbers):
output = []
for n in numbers:
output.append(n ** 2.5)
return output
# Improved version
# (Using List Comprehension)
def test_01_v1(numbers):
output = [n ** 2.5 for n in numbers]
return output
结果如下:
# Summary Of Test Results
Baseline: 32.158 ns per loop
Improved: 16.040 ns per loop
% Improvement: 50.1 %
Speedup: 2.00x
可以看到使用列表推导式可以得到2倍速的提高
2、在外部计算长度
如果需要依靠列表的长度进行迭代,请在for循环之外进行计算。
# Baseline version (Inefficient way)
# (Length calculation inside for loop)
def test_02_v0(numbers):
output_list = []
for i in range(len(numbers)):
output_list.append(i * 2)
return output_list
# Improved version
# (Length calculation outside for loop)
def test_02_v1(numbers):
my_list_length = len(numbers)
output_list = []
for i in range(my_list_length):
output_list.append(i * 2)
return output_list
通过将列表长度计算移出for循环,加速1.6倍,这个方法可能很少有人知道吧。
# Summary Of Test Results
Baseline: 112.135 ns per loop
Improved: 68.304 ns per loop
% Improvement: 39.1 %
Speedup: 1.64x
3、使用Set
在使用for循环进行比较的情况下使用set。
# Use for loops for nested lookups
def test_03_v0(list_1, list_2):
# Baseline version (Inefficient way)
# (nested lookups using for loop)
common_items = []
for item in list_1:
if item in list_2:
common_items.append(item)
return common_items
def test_03_v1(list_1, list_2):
# Improved version
# (sets to replace nested lookups)
s_1 = set(list_1)
s_2 = set(list_2)
output_list = []
common_items = s_1.intersection(s_2)
return common_items
在使用嵌套for循环进行比较的情况下,使用set加速498x
# Summary Of Test Results
Baseline: 9047.078 ns per loop
Improved: 18.161 ns per loop
% Improvement: 99.8 %
Speedup: 498.17x
4、跳过不相关的迭代
避免冗余计算,即跳过不相关的迭代。
# Example of inefficient code used to find
# the first even square in a list of numbers
def function_do_something(numbers):
for n in numbers:
square = n * n
if square % 2 == 0:
return square
return None # No even square found
# Example of improved code that
# finds result without redundant computations
def function_do_something_v1(numbers):
even_numbers = [i for n in numbers if n%2==0]
for n in even_numbers:
square = n * n
return square
return None # No even square found
这个方法要在设计for循环内容的时候进行代码设计,具体能提升多少可能根据实际情况不同:
# Summary Of Test Results
Baseline: 16.912 ns per loop
Improved: 8.697 ns per loop
% Improvement: 48.6 %
Speedup: 1.94x
5、代码合并
在某些情况下,直接将简单函数的代码合并到循环中可以提高代码的紧凑性和执行速度。
# Example of inefficient code
# Loop that calls the is_prime function n times.
def is_prime(n):
if n