Python,优化字符串连接的列表理解

Python, optimizing a list comprehension for string concatenation

我在通过列表理解处理字符串的脚本上使用 cProfile 到 运行 基准测试。我要优化的目标行如下所示:

signals = [('prefix' + str(day) + '_' + s) for s in signals]

其中 day 是一个整数。

这条特定的线路占用了整个 运行 时间的 33%。当然,它在执行过程中调用了百万次。

我尝试了几个明显的替代方案,包括 ''.join('prefix', str(day), '_', s)'prefix{:}_'.format(day),并使用 numpy.core.defchararray.add 连接通过 numpy.tile 与 [=18 创建的前缀数组=].它们都比列表理解慢 2 倍。

这条线路还有速度优化空间吗?

你试过了吗:

signals = ['prefix{0}_{1}'.format(day, s) for s in signals]

作为基准,如果您只使用元组而不是字符串会怎样?:

signals = [(day, s) for s in signals] 

这应该至少带来最小的改进:

# First precalculate the static part of the string
template = 'prefix%s_' % day + '%s'

# Then, use the %s string interpolation instead of joining strings with '+'  
# -->> Note: this proved to be wrong later... 
signals = [template % s for s in signals]

# Alternatively you could use map to compare efficiency (be aware of differences between python 2 and 3)
signals = map(template.__mod__, signals)

str.format的插值比%s的插值贵,所以我不打算尝试

现在让我们比较一下时间。你的方法:

>>> import timeit
>>> day = 45
>>> signals = ['aaaa', 'bbbb', 'cccccc', 'dddddddddddd']
>>> timeit.timeit("[('prefix' + str(day) + '_' + s) for s in signals]", 'from __main__ import day, signals')
1.35095184709592

我的第一个方法

>>> template = 'prefix%s_' % day + '%s'
>>> timeit.timeit("[template % s for s in signals]", 'from __main__ import template, signals')
0.7075940089748229

我的第二种方法

>>> timeit.timeit("map(template.__mod__, signals)", 'from __main__ import template, signals')
0.9939713030159822

所以,带有列表理解的模板的预计算似乎赢了。还有更多的事情需要考虑,例如,如果一个发电机对你来说足够好。

EDIT 从有趣的评论中指出的信息中,我添加了另一个解决方案:在紧密循环内部,我们只将两个字符串连接在一起,因此我们可以直接连接它们% 格式化

>>> template = 'prefix%s_' % day
>>> timeit.timeit("[template + s for s in signals]", 'from __main__ import template, signals')
0.39771016975851126

目前谁是赢家。

这样会更快

import numpy as np
signal = [x for x in range(9000)]
length = len(signal) 
prefArray = np.array(['prefix']*length )
dArray = np.array([str(day)]*length )
cArray = np.array(['_']*length )
sArray = np.array(["%s"%x for x in signal])

firstArray = np.core.defchararray.add(prefArray, dArray)
secondArray = np.core.defchararray.add(cArray, sArray)
result = np.core.defchararray.add(firstArray,secondArray)
print result