用于构建并行列表的Pythonic模式

时间:2016-12-13 18:17:48

标签: python list python-3.x

我是Python的新手,我发现我一遍又一遍地编写相同的代码模式:

def foo(list):
    results = []
    for n in list:
        #do some or a lot of processing on N and possibly other variables
        nprime = operation(n)
        results.append(nprime)
    return results

我正在考虑创建空列表,然后是append调用。是否有更多的Pythonic方式来表达这种模式? append可能没有最佳性能特征,但我不确定如何在Python中使用它。

我经常知道输出的长度,所以每次调用append似乎都可能导致内存碎片或性能问题,但我也想知道这是不是我的旧{{1}绊倒我的方式我正在编写很多文本解析代码,这些代码在任何特定的循环或片段上都不具有超级性能敏感性,因为所有性能都包含在Cgensim代码中,并且功能更强大比我的。

进行此类操作是否有更好/更多的pythonic模式?

2 个答案:

答案 0 :(得分:8)

首先,列表理解可能就是您所需要的(如果评论中提到的所有处理都发生在operation中。

def foo(list):
    return [operation(n) for n in list]

如果列表理解在您的情况下不起作用,请考虑foo是否真的需要构建列表,而不是生成器。

def foo(list):
    for n in list:
        # Processing...
        yield operation(n)

在这种情况下,您可以迭代序列,并按需计算每个值:

for x in foo(myList):
   ...

或者您可以让来电者决定是否需要完整列表:

results = list(foo())

如果上述两种方法都不合适,那么现在就像现在一样在循环体中建立返回列表是完全合理的。

答案 1 :(得分:4)

  

[..]所以每次调用append似乎都可能导致内存碎片或性能问题,但我也想知道这是不是我的旧C方式绊倒了我。

如果您对此感到担忧,请不要这样做。当需要重新调整列表大小(列表根据其大小动态调整大小)以执行O(1)追加时,Python会过度分配。您可以手动调用list.append或使用列表推导构建它(内部使用.append),内存方式的效果类似。

列表理解只是表现得更好(速度更快);它针对创建具有专用字节码指令的列表进行了优化(LIST_APPEND主要是直接调用C附加的列表。

当然,如果关注内存使用情况,您可以随时选择生成器方法,因为在chepners中突出显示,可以轻松地生成结果。

最后,for循环仍然很棒。与理解和map相比,它们看起来很笨拙,但它们仍然提供了一种可识别且可读的方式来实现目标。 for循环也值得我们的爱。