详解Python列表推导(list comprehension)

本文将介绍列表推导的优势、底层原理和注意事项

列表推导的优势

列表推导的优势有两点一是语法简洁,例如:

l1 = [i for i in range(10)]
l2 = []
for i in range(10):
    l2.append(i)

print(l1 == l2) # 输出:True

上面例子中l1采用列表推导生成,l2使用常规的Python代码生成。生成的列表l1、l2是相同的,但是明显看出l2更”啰嗦“。
第二个优点是快,列表推导要比常规的代码生成列表要快的多,例如:

start = time.time()
l1 = [i for i in range(10000000)]
end = time.time()
print("列表推导式用时:", end - start) # 列表推导式用时: 0.5695033073425293

l2 = []
start = time.time()
for i in range(10000000):
    l2.append(i)
end = time.time()
print("正常写法用时:", end - start) # 正常写法用时: 1.5050091743469238

print(l1 == l2) # 输出:True

在博主2017款 mbp Cython 的运行环境下生成一千万元素的列表 列表推导的速度比for 循环的方式要快 2.5 倍左右。

列表推导快速的原因

我用下列代码作为实例:

def A():
    l1 = [i for i in range(10000000)]
    return l1

def B():
    l2 = []
    for i in range(10000000):
        l2.append(i)
    return l2


if __name__ == '__main__':
    import dis
    print("函数A的字节码:")
    dis.dis(A)
    print("函数B的字节码:")
    dis.dis(B)

输出如下:

函数A的字节码:
  7           0 LOAD_CONST               1 
              2 LOAD_CONST               2 
              4 MAKE_FUNCTION            0
              6 LOAD_GLOBAL              0 (range)
              8 LOAD_CONST               3 (10000000)
             10 CALL_FUNCTION            1
             12 GET_ITER
             14 CALL_FUNCTION            1
             16 STORE_FAST               0 (l1)

  8          18 LOAD_FAST                0 (l1)
             20 RETURN_VALUE
函数B的字节码:
 11           0 BUILD_LIST               0
              2 STORE_FAST               0 (l2)

 12           4 SETUP_LOOP              26 (to 32)
              6 LOAD_GLOBAL              0 (range)
              8 LOAD_CONST               1 (10000000)
             10 CALL_FUNCTION            1
             12 GET_ITER
        >>   14 FOR_ITER                14 (to 30)
             16 STORE_FAST               1 (i)

 13          18 LOAD_FAST                0 (l2)
             20 LOAD_ATTR                1 (append)
             22 LOAD_FAST                1 (i)
             24 CALL_FUNCTION            1
             26 POP_TOP
             28 JUMP_ABSOLUTE           14
        >>   30 POP_BLOCK

 14     >>   32 LOAD_FAST                0 (l2)
             34 RETURN_VALUE

从上图中的字节码可以看出,使用for循环的时候要先声明空列表,之后不断对 i 进行赋值,加载append方法,相比使用列表推导的方式多执行了很多字节码,所以使用列表推导在解释器层面是做过优化的,Python官方也推荐这个做法

列表推导的局限

  1. 不适合在for 循环中加入过于复杂的逻辑
  2. 在Python 2.x 中 列表推导中的变量会泄漏到列表推导之外,但在Python3中列表推导和其他的一些推导具有自己的变量作用域
  3. 可读性不高

转载注明出处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值