pythonfor循环加法_python中,for循环,map函数,list comprehension列表推导的效率比较...

在我们平时写代码中,肯定会遇到不少从一个列表向另一个列表进行转化的操作,以给列表中每个int元素+1为例,通常我们会用到一下3种方式:

array = range(1000)#循环

a =[]for i inarray:

a.append(i+1)#map函数

a = map(lambda x: x+1, array)#列表推导

a = [x+1 for x in array]

究竟以上三种写法有何差异,哪种写法最好,之前读google的代码规范说推荐第三种列表推导,那么为什么推荐列表推导?

我们在ipython中用timeit进行一下简单的评测:

#循环

array=range(1000)

a=[]%timeit for i in array: a.append(i+1)#1000 loops, best of 3: 156 us per loop

#map函数

%timeit map(lambda x: x+1, array)#10000 loops, best of 3: 172 us per loop

#列表推导

%timeit [x+1 for x inarray]#10000 loops, best of 3: 68.7 us per loop

可以看出列表推导的优势是非常明显的

为什么会造成这种情况呢?我们用dis模块查看各个方法调用了哪些底层资源

deftest_for(array):

a=[]for i inarray:

a.append(i+1)returna

dis.dis(test_for)20 BUILD_LIST 03 STORE_FAST 1(a)3 6 SETUP_LOOP 31 (to 40)9LOAD_FAST 0 (array)12GET_ITER>> 13 FOR_ITER 23 (to 39)16 STORE_FAST 2(i)4 19 LOAD_FAST 1(a)22LOAD_ATTR 0 (append)25 LOAD_FAST 2(i)28 LOAD_CONST 1 (1)31BINARY_ADD32 CALL_FUNCTION 1

35POP_TOP36 JUMP_ABSOLUTE 13

>> 39POP_BLOCK5 >> 40 LOAD_FAST 1(a)43 RETURN_VALUE

可以看出for循环中,在主循环体,程序反复调用load和call

deftest_map(array):return map(lambda x: x+1, array)

dis.dis(test_map)20 LOAD_GLOBAL 0 (map)3 LOAD_CONST 1 ( at 0x29e4cb0, file "", line 2>)6MAKE_FUNCTION 09LOAD_FAST 0 (array)12 CALL_FUNCTION 2

15 RETURN_VALUE

map循环时构造了一个匿名函数,并且用map调用了该函数call

deftest_list(array):return [x+1 for x inarray]

dis.dis(test_list):20 BUILD_LIST 03LOAD_FAST 0 (array)6GET_ITER>> 7 FOR_ITER 16 (to 26)10 STORE_FAST 1(x)13 LOAD_FAST 1(x)16 LOAD_CONST 1 (1)19BINARY_ADD20 LIST_APPEND 2

23 JUMP_ABSOLUTE 7

>> 26 RETURN_VALUE

列表推导居然使用了LIST_APPEND这样一个东西去记录结果

我们都知道调用底层的速度会更快,所以说用列表推导的方式会更快一些,因为他并没有调用其他的函数

那么如何修改前两种方法,使其速度更快呢?

1,for循环,我们留意到for循环中有两个步骤,一是load,而是call,如果把load的过程记录下来,那么速度就会更快一些

a =[]

test_func=a.append%timeit for i in array: test_func(i+1)#10000 loops, best of 3: 100 us per loop

比较之前的写法,有大幅度的提升

2,map函数,我们在一开始的测试中使用的是我们自定义的lambda匿名函数,如果将该匿名函数设置为底层的简单加法,那么其速度也会有大幅提升

int_obj=1

%timeit map(int_obj.__add__, array)#10000 loops, best of 3: 67.6 us per loop

我们惊奇的发现其速度和列表推导几乎一样

接下来就有一个问题:为什么有列表推导,还要有for呢?如果对于一个复杂的转换操作,列表推导的效率其实和for是差不多的

defadd(x):return x+1

%timeit [add(x) for x inarray]#1000 loops, best of 3: 180 us per loop

总上所述:简单的循环映射操作,我们建议用列表推导形式,其效率更高,速度更快。复杂的循环映射操作,我们建议用for循环,这样的代码更加易读易懂。而对于map方法,我们认为这是一种过时的写法,应当少用,甚至不用。

参考:https://www.zhihu.com/question/34637934

以上结果实测:python 2.7.3,ipython 0.12.1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值