Skip to main content
 首页 » 编程设计

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

2025年05月04日21Renyi-Fan

我正在使用 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 创建的前缀数组与 signals。它们都比列表理解慢 2 倍。

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

请您参考如下方法:

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

# 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 

因此,具有列表理解的模板的预计算似乎获胜。还有其他事情需要考虑,例如,发电机是否对您足够好。

编辑 根据有趣的评论中指出的信息,我添加了另一个解决方案:在紧密循环内,我们只将两个字符串连接在一起,因此我们可以直接连接它们而不是 %-formatting

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

目前谁是赢家。