dis的作用看python每一步做了什么,每次找这个方法都需要很多的时间,这次直接粘贴过来

从这个问答粘贴过来的,原来的地址实在是找不到了。
https://zhidao.baidu.com/question/691387631487105364.html

 
首先肯定 map 和列表推导效率确实会比循环的高,

先说列表推导,下边是我在 ipython 里的测试结果(测试环境 Python 2.7.10):

>>> long_list = range(1000)

>>> a = []

>>> %timeit for i in long_list: a.append(i+1)
10000 loops, best of 3: 100 µs per loop

>>> %timeit [i+1 for i in long_list]
10000 loops, best of 3: 43.3 µs per loop

可以看出列表推导还是要快过 for 循环的。

那为什么列表推导会快呢?我们直接调用 python 的 dis 模块去看看他的字节码:

这个是列表推导那一行代码的字节码:
0 BUILD_LIST 0
3 LOAD_GLOBAL 0 (long_list)
6 GET_ITER
>> 7 FOR_ITER 16 (to 26)
10 STORE_FAST 0 (i)
13 LOAD_FAST 0 (i)
16 LOAD_CONST 1 (1)
19 BINARY_ADD
20 LIST_APPEND 2
23 JUMP_ABSOLUTE 7
...

这个是 for 循环那一行的字节码:
6 SETUP_LOOP 31 (to 40)
9 LOAD_GLOBAL 0 (long_list)
12 GET_ITER
>> 13 FOR_ITER 23 (to 39)
16 STORE_FAST 1 (i)
19 LOAD_FAST 0 (a)
22 LOAD_ATTR 1 (append)
25 LOAD_FAST 1 (i)
28 LOAD_CONST 1 (1)
31 BINARY_ADD
32 CALL_FUNCTION 1
35 POP_TOP
36 JUMP_ABSOLUTE 13
...

对比一下不难发现其实列表推导和 for 循环的过程几乎是一样的,除了如何append。所以你要说他是语法糖也不是不行……


列表推导中直接使用了‘LIST_APPEND’这个字节码来实现 append 功能,效率相当的高。而在 for 循环中每次循环都要先载入
append 这个属性然后再 ‘CALL_FUNCTION’一下。这样势必就会慢了很多。为了验证我们的猜想,我们把 append
这个函数存到局部变量里去:

>>> a = []

>>> invoke = a.append

>>> %timeit for i in long_list: invoke(i+1)
10000 loops, best of 3: 67.2 µs per loop

发现没有比前一个版本的 for 循环快了接近40%,剩下的多出来20多 µs 的开销自然就是‘CALL_FUNCTION’的开销咯 ╮(╯_╰)╭。

相信到这里你应该明白了为什么列表推导要比 for 循环快吧,秘诀就在这个‘LIST_APPEND’这个字节码上,相当于你直接调用了 C 语言版本的函数(不严谨)而且越过了一些中间步骤。

接下来简单说说 map 的事情,直接使用 map 一般来说是要比循环快的,但有的时候情况会比较诡异,例如:
>>> %timeit for i in long_list: a.append(i+1)
10000 loops, best of 3: 100 µs per loop

>>> %timeit map(lambda x: x+1, long_list)
10000 loops, best of 3: 109 µs per loop

别急,我们把 map 的写法改成这样:
>>> int_object = 1

>>> %timeit map(int_object.__add__, long_list)
10000 loops, best of 3: 41.6 µs per loop

于是神奇的事情出现了!基本上和列表推导一样快!(⊙o⊙)

这个主要是因为 lambda
表达式生成的函数是 Python 的,而直接用+运算符或者__add__方法调用的是 C 版本的。你要是把列表推导里边的+换成 lambda
表达式两者的速度差不多,map 一般来说还要快上一点点。本质上来说 map 调用了底层的 C 函数所以速度自然是快的。粗暴的总结一下就是不用
lambda 的时候 map 要快一些
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值