在长字符串上没有 lambda 的列表理解和映射

list comprehension and map without lambda on long string

$ python -m timeit -s'tes = "987kkv45kk321"*100' 'a = [list(i) for i in tes.split("kk")]'
10000 loops, best of 3: 79.4 usec per loop

$ python -m timeit -s'tes = "987kkv45kk321"*100' 'b = list(map(list, tes.split("kk")))'
10000 loops, best of 3: 66.9 usec per loop

$ python -m timeit -s'tes = "987kkv45kk321"*10' 'a = [list(i) for i in tes.split("kk")]'
100000 loops, best of 3: 8.34 usec per loop

$ python -m timeit -s'tes = "987kkv45kk321"*10' 'b = list(map(list, tes.split("kk")))'
100000 loops, best of 3: 7.38 usec per loop

$ python -m timeit -s'tes = "987kkv45kk321"' 'a = [list(i) for i in tes.split("kk")]'
1000000 loops, best of 3: 1.51 usec per loop

$ python -m timeit -s'tes = "987kkv45kk321"' 'b = list(map(list, tes.split("kk")))'
1000000 loops, best of 3: 1.63 usec per loop

我尝试使用 timeit 并想知道为什么从具有列表理解的 string.split() 创建列表列表对于较短的字符串来说更快而对于更长的字符串更慢。

这种时机基本没用。

您获得的时间范围以微秒为单位 - 您只是在每次交互中创建数十个不同的单字符长元素列表。你得到的基本上是线性类型,因为你创建的对象数量与你的字符串长度成正比。对此几乎没有任何意外。

map 的固定设置成本高于 listcomp 解决方案的设置成本。但是 map 的每件商品成本较低。因此,对于短输入,map 支付的固定设置成本要多于节省的每件商品成本(因为商品太少)。当项目数量增加时,map 的固定设置成本不会改变,但更多项目正在收获每件项目的节省,因此 map 慢慢领先。

map 节省的东西:

  1. 只查找 list 一次(在首先检查嵌套和全局范围之后,listcomp 必须在每个循环中在内置命名空间中查找它,因为它不能保证 list不会从一个循环到另一个循环被覆盖)
  2. 每个项目不执行Python字节码(因为映射函数也是C级的),所以解释器根本不参与,减少热C级代码量

map 在实际调用 map 时失败(C 内置函数比 运行 快,但调用起来相对较慢,尤其是当它们采用可变长度参数时) ,以及 map 对象的创建和清理(listcomp 闭包是预先编译的)。但正如我上面提到的,这些都与输入的大小无关,所以如果映射函数是 C 内置的,你可以快速弥补它。