Python 优化复杂列表理解语句
如何优化Python 优化复杂列表理解语句,python,list,algorithm,performance,list-comprehension,Python,List,Algorithm,Performance,List Comprehension,如何优化第3步中的列表理解语句? 背景: 在现实世界中: r包含约500个元素和 a包含约100万个元素 请注意,步骤3是r和a上的嵌套循环。因此,这需要很多时间。在下面的代码中,为了简单起见,缩短了r和a 出于背景目的,我还提到了这个函数,some\u-heavy\u-calculation()。这个函数在这里没有显示,但由于它也被称为len(r)*len(a)次,因此它也会消耗大量时间 为了加快速度,我注意到,通过引入“更快”选项,我可以避免90-95%的调用一些较重的计算()。唯一的问
第3步中的列表理解语句?
背景:
在现实世界中:
包含约500个元素和r
包含约100万个元素a
步骤3
是r
和a
上的嵌套循环。因此,这需要很多时间。在下面的代码中,为了简单起见,缩短了r
和a
出于背景目的,我还提到了这个函数,some\u-heavy\u-calculation()
。这个函数在这里没有显示,但由于它也被称为len(r)*len(a)
次,因此它也会消耗大量时间
为了加快速度,我注意到,通过引入“更快”选项,我可以避免90-95%的调用一些较重的计算()
。唯一的问题是步骤3
现在需要很多时间。事实上,这一步耗费的时间比我所能节省的要多
def some_heavy_calculation(rules, data) -> list:
# ...
return []
# r = input rules
r = ['x', 'y', 'z']
# a = input data
a = [7, 7, 7, 4, 4, 2, 2, 8, 2, 9, 4, 4, 8, 7 ]
#########
# Slow alternative: b = result of some_heavy_calculation(r, a)
# b = expected result, size: [ r x a ]
b = [[True, True, True, True, True, True, True, True, True, False, True, True, True, True],
[True, True, True, False, False, True, True, True, True, False, False, False, True, True],
[False, False, False, True, True, False, False, True, False, False, True, True, True, False]]
#########
#########
# Faster:
# Since these steps avoids 90-95 % of all the calls to some_heavy_calculation()
#
# Step 1: c = a in order, but without duplicates
c = [7, 4, 2, 8, 9 ]
# Step 2: d = result of calculation, size: [ r x c ]
d = [[True, True, True, True, False ],
[True, False, True, True, False ],
[False, True, False, True, False ]]
# Step 3: e = should equal b
e = [[d[ri][next(ci for ci, cv in enumerate(c) if cv == av)] for ai, av in enumerate(a)] for ri, rv in enumerate(r)]
#########
str(b) == str(e) # <--- returns True
def一些繁重的计算(规则、数据)->列表:
# ...
返回[]
#r=输入规则
r=['x','y','z']
#a=输入数据
a=[7,7,7,4,4,2,2,8,2,9,4,4,8,7]
#########
#慢备选方案:b=一些重计算的结果(r,a)
#b=预期结果,大小:[r x a]
b=[[真,真,真,真,真,真,真,真,假,真,真,真,真,真],
[真,真,真,假,假,真,真,真,真,假,假,假,假,真,真],
[假,假,假,真,真,假,假,真,假,假,真,真,真,真,假]]
#########
#########
#更快:
#因为这些步骤避免了90-95%的对某些计算()的调用
#
#步骤1:c=a按顺序排列,但无重复项
c=[7,4,2,8,9]
#步骤2:d=计算结果,尺寸:[r x c]
d=[[True,True,True,True,False],
[真,假,真,真,假],
[假,真,假,真,假]]
#步骤3:e=应等于b
e=[[d[ri][next(ci代表ci,cv代表枚举(c)中的cv,如果cv==av)]代表ai,av代表枚举(a)]代表ri,rv代表枚举(r)]
#########
str(b)==str(e)#在我看来,您需要的是一个名为
有一个decorator(对于Python<3.9,您可以使用)可以这样使用:
import functools
@functools.cache
def some_heavy_calculation_per_item(rules, value) -> bool:
# ...
return []
def some_heavy_calculation(rules, data) -> list:
# ...
returned = []
for value in data:
returned.append(some_heavy_calculation_per_item(rules, value))
return returned
使用memorization可以有效地对每个值进行一次计算(如您所述,可以节省90-95%),但也可以采用内存高效的方式(无需组合许多大型列表或数组)
另一种可能的优化方法是使用yield
而不是在some\u-heavy\u-calculation
函数中构建列表,但这取决于您使用结果的方式-如果逐值计算,则yield
ing将提高性能。如果你需要完整的列表,那么它将毫无帮助。列表理解只是一种从d
中查找与r
和a
元素相对应的元素的方法吗?是的,确切地说,只是不使用枚举(a)
中的ai
值。美好的我一点也没听说过。即使并行地执行一些重的计算()也行吗。我使用的是Pool(processs=8)和Pool.map(partial(some_function,…),rules),其中some_function()反过来应用some_-heavy_计算()。是的,每个进程都应该构造一个单独的缓存,这样可能会有一些重复(在最坏的情况下,您必须检查它-每个进程分别初始化缓存函数)。。但是,您可以明智地将相同的值发送到相同的进程—只需将值发送到id=number%8
(%
为模)的进程即可—缓存的使用将非常有效,并且只需计算一次结果。