首页 > 解决方案 > 提高使用 for 循环的代码的性能

问题描述

我正在尝试根据一些数据创建一个列表,但是当我在大数据上运行它时,我使用的代码非常慢。所以我怀疑我并没有使用 Python 的所有功能来完成这项任务。在 Python 中有没有更有效和更快的方法来做到这一点?

这里是代码的解释:

你可以把这个问题想象成一个游戏列表(list_type),每个游戏都有一个参与团队的列表和游戏中每个团队的得分(list_xx)。对于当前游戏中的每一对,它首先计算总和与以往比赛的得分差异(win_comp_past_difs);仅包括当前游戏中的配对。然后它用分数差异更新当前游戏中的每一对。使用 defaultdict 跟踪每对游戏中每对的分数,并在玩每场游戏时更新这个分数。

在下面的示例中,根据一些数据,有用于创建新变量的 for 循环list_zz

数据和for循环代码:

import pandas as pd
import numpy as np
from collections import defaultdict
from itertools import permutations

list_type = [['A', 'B'], ['B'], ['A', 'B', 'C', 'D', 'E'], ['B'], ['A', 'B', 'C'], ['A'], ['B', 'C'], ['A', 'B'], ['C', 'A', 'B'], ['A'], ['B', 'C']]

list_xx = [[1.0, 5.0], [3.0], [2.0, 7.0, 3.0, 1.0, 6.0], [3.0], [5.0, 2.0, 3.0], [1.0], [9.0, 3.0], [2.0, 7.0], [3.0, 6.0, 8.0], [2.0], [7.0, 9.0]]

list_zz= []
#for-loop
wd = defaultdict(float)
for i, x in zip(list_type, list_xx):
    # staff 1
    if len(i) == 1:
        #print('NaN')
        list_zz.append(np.nan)
        continue
    # Pairs and difference generator for current game (i)
    pairs = list(permutations(i, 2))
    dgen = (value[0] - value[1] for value in permutations(x, 2))
    # Sum of differences from previous games incluiding only pair of teams in the current game
    for team, result in zip(i, x):
        win_comp_past_difs = sum(wd[key] for key in pairs if key[0] == team)
        #print(win_comp_past_difs)
        list_zz.append(win_comp_past_difs)
    # Update pair differences for current game
    for pair, diff in zip(pairs, dgen):
        wd[pair] += diff
print(list_zz)

看起来像这样:

[0.0,
 0.0,
 nan,
 -4.0,
 4.0,
 0.0,
 0.0,
 0.0,
 nan,
 -10.0,
 13.0,
 -3.0,
 nan,
 3.0,
 -3.0,
 -6.0,
 6.0,
 -10.0,
 -10.0,
 20.0,
 nan,
 14.0,
 -14.0]

如果您能详细说明代码以使其更高效并更快地执行,我将不胜感激。

标签: pythonperformance

解决方案


在不审查代码的整体设计的情况下,我突然想到了一项改进:将代码移动到函数中。

正如目前所写,您使用的所有变量都是全局变量。由于全局命名空间的动态特性,Python 必须在每次使用访问它时查找您使用的每个全局变量。(1)在 CPython 中,这对应于哈希表查找,这可能很昂贵,尤其是在存在哈希冲突的情况下。

相反,局部变量可以在编译时知道,因此存储在一个固定大小的数组中。因此,访问这些变量只涉及取消引用一个指针,这相对要快得多。

考虑到这一原则,您应该能够通过将所有代码移动到“主”函数中来提高性能(运行时间减少 40% 左右):

def main():
    ...
    # Your code here

if __name__ == '__main__':
    main()

(1) 来源


推荐阅读