在长字符串上没有 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
节省的东西:
- 只查找
list
一次(在首先检查嵌套和全局范围之后,listcomp 必须在每个循环中在内置命名空间中查找它,因为它不能保证 list
不会从一个循环到另一个循环被覆盖)
- 每个项目不执行Python字节码(因为映射函数也是C级的),所以解释器根本不参与,减少热C级代码量
map
在实际调用 map
时失败(C 内置函数比 运行 快,但调用起来相对较慢,尤其是当它们采用可变长度参数时) ,以及 map
对象的创建和清理(listcomp 闭包是预先编译的)。但正如我上面提到的,这些都与输入的大小无关,所以如果映射函数是 C 内置的,你可以快速弥补它。
$ 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
节省的东西:
- 只查找
list
一次(在首先检查嵌套和全局范围之后,listcomp 必须在每个循环中在内置命名空间中查找它,因为它不能保证list
不会从一个循环到另一个循环被覆盖) - 每个项目不执行Python字节码(因为映射函数也是C级的),所以解释器根本不参与,减少热C级代码量
map
在实际调用 map
时失败(C 内置函数比 运行 快,但调用起来相对较慢,尤其是当它们采用可变长度参数时) ,以及 map
对象的创建和清理(listcomp 闭包是预先编译的)。但正如我上面提到的,这些都与输入的大小无关,所以如果映射函数是 C 内置的,你可以快速弥补它。