Fluent Python 学习--列表解析生成器表达式
列表解析(推导)和生成器表达式
1 列表推导
列表推导式构建列表的快捷方式,生成器表达式则可以用来
创建其他任何类型的序列
1.1 列表解析的代码易读性
先看for循环的方式
symblos = "abcdef"
codes = []
for symblo in symblos:
codes.append(ord(symblo))
print(codes)
列表解析
symblos = "abcdef"
codes = [ord(symblo) for symblo in symblos]
print(codes)
列表推导也可能被滥.用通常的原则是,只用列表推导来创建新的列表,并且尽量保持简短。如果列表推导的代码超过了两行,你可能就要考虑是不是得用 for 循环重写了
1.2 解决变量泄露的问题
Python中的列表中for后面和前面有同名变量,在Python2中会覆盖,在Python3中没有问题。
#Python2中
>>> x='hello' #这个全局变量x
>>> code = [x for x in 'abc']
>>> x
'c' # 经过for循环后x会用c替换hello
Python3中
x = 'hello'
code = [x for x in "abc"]
print(x) # 结果是hello
在Python3中的列表解析,有自己的局部作用域,类似函数。(生成器表达式也是同样的)
表达式内部的变量和赋值只在内部起作用。表达式的上下文里的同名变量还可以被正常引用,局部变量并不会影响到它们。
1.3 列表推导同filter和map的比较
filter 和 map 合起来能做的事情,列表推导也可以做,而且还不需要借助难以理解和阅读的 lambda 表达式
symblos = "abcdef"
code =list(filter(lambda c:c>99,map(ord,symblos)))
print(code)
filter(函数,sequence)
map(函数,sequence)
fliter/map 组合不一定比列表解析快
下面的代码是书中的测试代码,
代码地址:
https://github.com/fluentpython/example-code/blob/master/02-array-seq/listcomp_speed.py#L8
import timeit
TIMES = 10000
SETUP = """
symbols = '$¢£¥€¤'
def non_ascii(c):
return c > 127
"""
def clock(label, cmd):
res = timeit.repeat(cmd, setup=SETUP, number=TIMES)
print(label, *('{:.3f}'.format(x) for x in res))
clock('listcomp :', '[ord(s) for s in symbols if ord(s) > 127]')
clock('listcomp + func :', '[ord(s) for s in symbols if non_ascii(ord(s))]')
clock('filter + lambda :', 'list(filter(lambda c: c > 127, map(ord, symbols)))')
clock('filter + func :', 'list(filter(non_ascii, map(ord, symbols)))')
listcomp : 0.017 0.013 0.014
listcomp + func : 0.019 0.020 0.019
filter + lambda : 0.017 0.019 0.025
filter + func : 0.021 0.023 0.024
listcomp : 0.013 0.014 0.013
listcomp + func : 0.020 0.020 0.023
filter + lambda : 0.024 0.022 0.022
filter + func : 0.016 0.016 0.016
结果是list快于filter/map,运行的时候确保自己的机器没有运行占用CPU的软件
1.4 笛卡尔积
用列表解析可以生成两个或者以上的可迭代笛卡尔积,笛卡尔积是一个列表,列表里的元素是由输入的可迭代类型的元素对构成的元组,因此笛卡儿积列表的长度等于输入变量的长度的乘积
1.4.1 Python 实现
- 列表解析的方式
colors = ['blck','white']
sizes = ['S','M','L']
tshits = [(color,size) for color in colors for size in sizes]
print(tshits)
python中的[] {} () 会忽略其中的换行,就不用\来表示
- for 循环的方法
colors = ['blck','white']
sizes = ['S','M','L']
for color in colors:
for size in sizes:
print(color,size)
2 生成器表达式
生成器表达式可以推导出元组、数组或者其他数据类型,生成器的原理是迭代器协议。把[]换成()就是生成器
生成器取的时候通过next取,只能一个个的取,通过for循环能全部取出来
symblos = "abcdef"
code = (ord(symbol) for symbol in symblos)
print(next(code))#一个个的取
#通过for循环遍历
for i in code:
print(i)
通过生成器生成元组
symblos = "abcdef"
code = tuple(ord(symbol) for symbol in symblos)
print(type(code))# tuple
通过生成器生成数组
import array
symblos = "abcdef"
code=array.array('I',(ord(symbol) for symbol in symblos))
print(code)
# 这个是数组的第一个参数(must be b, B, u, h, H, i, I, l, L, q, Q, f or d)
使用生成器生成笛卡尔积
通过for循环遍历全部生成
colors = ['blck','white']
sizes = ['S','M','L']
for i in ((color,size) for color in colors for size in sizes):
print(i)

浙公网安备 33010602011771号