【问题标题】:Python: why partition(sep) is faster than split(sep, maxsplit=1)Python:为什么 partition(sep) 比 split(sep, maxsplit=1) 快
【发布时间】:2017-12-20 03:50:51
【问题描述】:

我发现一个有趣的事情是partitionsplit 在分隔符后获取整个子字符串时更快。我已经在 Python 3.5 和 3.6 (Cpython) 中测试过

In [1]: s = 'validate_field_name'

In [2]: s.partition('_')[-1]
Out[2]: 'field_name'

In [3]: s.split('_', maxsplit=1)[-1]
Out[3]: 'field_name'

In [4]: %timeit s.partition('_')[-1]
220 ns ± 1.12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [5]: %timeit s.split('_', maxsplit=1)[-1]
745 ns ± 48.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [6]: %timeit s[s.find('_')+1:]
340 ns ± 1.44 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

我浏览了Cpython源代码,发现partition使用FASTSEARCH算法,见here。而split 仅在分隔符字符串的长度大于 1 时使用FASTSEARCH,参见here。但是我已经测试了长度更大的 sep 字符串。我得到了同样的结果。

我猜原因是partition 返回一个三元素元组,而不是一个列表。

我想知道更多细节。

【问题讨论】:

  • 是的,部分原因是构建固定长度的元组比构建任意长度的列表更有效。
  • 您还使用关键字参数调用split,即s.split('_', maxsplit=1),而不是简单的s.split('_', 1)

标签: python string algorithm performance cpython


【解决方案1】:

微基准可能会产生误导

py -m timeit "'validate_field_name'.split('_', maxsplit=1)[-1]"
1000000 loops, best of 3: 0.568 usec per loop

py -m timeit "'validate_field_name'.split('_', 1)[-1]"
1000000 loops, best of 3: 0.317 usec per loop

仅将参数作为位置或关键字传递会显着改变时间。所以我猜测分区更快的另一个原因,因为它不需要第二个参数......

【讨论】:

  • 太棒了。我同意你所说的,但我测试了一个什么都不做的简单函数并得到以下结果。在 [16] 中:def func(a, b): ...: pass ...: 在 [17] 中:%timeit func(1, 2) 每个循环 95.8 ns ± 1.72 ns(平均值 ± 标准偏差7 次运行,每次 10000000 次循环)在 [18] 中:%timeit func(1, b=2) 123 ns ± 2.3 ns 每个循环(7 次运行的平均值±标准偏差,每次 10000000 次循环)差异并不明显。我认为内置功能很特别。它需要一些其他优化。
猜你喜欢
  • 1970-01-01
  • 2014-04-02
  • 2013-06-09
  • 1970-01-01
  • 2013-09-13
  • 1970-01-01
  • 1970-01-01
  • 2017-10-20
  • 2014-11-06
相关资源
最近更新 更多