我是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}绊倒我的方式我正在编写很多文本解析代码,这些代码在任何特定的循环或片段上都不具有超级性能敏感性,因为所有性能都包含在C
或gensim
代码中,并且功能更强大比我的。
进行此类操作是否有更好/更多的pythonic模式?
答案 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
循环也值得我们的爱。