解析式的定义
解析式是将一个可迭代对象转换成另一个可迭代的工具。在转换过程中,可以指定元素必须符合一定的条件,才能添加至新的可迭代对象中,这样每个元素都可以按需要进行转换。
解析式的用法
列表解析
列表解析返回的是列表
1). for循环常规的写法
求一个列表中所有元素的平方
>>> lst = list(range(10))
>>> lst
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ret = []
>>> for x in lst:
... ret.append(x ** 2)
...
>>> ret
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
使用解析式的方式,将上面的例子写下
>>> lst
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ret = [x ** 2 for x in lst] 列表解析
>>> ret
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
2). 带有判断的解析式
获取列表中所有的偶数
常规的写法
>>> lst
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ret = []
>>> for x in lst:
... if x % 2 == 0:
... ret.append(x)
...
>>> ret
[0, 2, 4, 6, 8]
使用解析式的写法
>>> lst
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ret = [x for x in lst if x % 2 == 0 ]
>>> ret
[0, 2, 4, 6, 8]
3). 带有多个判断的解析式
获取列表中所有偶数,并且大于0
>>> lst
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ret = [x for x in lst if x % 2 == 0 if x > 0]
>>> ret
[2, 4, 6, 8]
获取列表中所有偶数,并且大于0,小于5
>>> lst
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ret = [x for x in lst if x % 2 == 0 if x > 0 if x < 5]
>>> ret
[2, 4]
4). 使用逻辑运算的解析式
获取列表中所有偶数,并且大于0,小于5
>>> lst
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> ret = [x for x in lst if x > 0 and x < 5 and x % 2 == 0]
>>> ret
[2, 4]
带多个if判断的语句,都是可以转化为调教的逻辑运算,所以一般来说,不会带多个if语句
5). 多个for的解析式
常规写法
>>> ret = []
>>> for x in range(2):
... for y in range(2,4):
... ret.append((x,y))
...
>>> ret
[(0, 2), (0, 3), (1, 2), (1, 3)]
解析式写法
>>> ret = [(x,y) for x in range(2) for y in range(2,4)]
>>> ret
[(0, 2), (0, 3), (1, 2), (1, 3)]
>>> for i in ret:
... print(i)
...
(0, 2)
(0, 3)
(1, 2)
(1, 3)
在解析式中,是可以有多个for的,就是逐一按照上面的格式增加就好了,相当于逐层嵌套for循环
6). for 和 if语句结合的解析式
常规写法
>>> ret = []
>>> for x in range(5):
... if x > 0:
... for y in range(5,10):
... ret.append((x,y))
>>> for i in ret:
... print(i)
...
(1, 5)
(1, 6)
(1, 7)
(1, 8)
(1, 9)
(2, 5)
(2, 6)
(2, 7)
(2, 8)
(2, 9)
(3, 5)
(3, 6)
(3, 7)
(3, 8)
(3, 9)
(4, 5)
(4, 6)
(4, 7)
(4, 8)
(4, 9)
解析式写法
>>> ret = [(x,y) for x in range(5) if x > 0 for y in range(5,10)]
>>> ret
[(1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (2, 5), (2, 6), (2, 7), (2, 8), (2, 9), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (4, 5), (4, 6), (4, 7), (4, 8), (4, 9)]
>>> for i in ret:
... print(i)
...
(1, 5)
(1, 6)
(1, 7)
(1, 8)
(1, 9)
(2, 5)
(2, 6)
(2, 7)
(2, 8)
(2, 9)
(3, 5)
(3, 6)
(3, 7)
(3, 8)
(3, 9)
(4, 5)
(4, 6)
(4, 7)
(4, 8)
(4, 9)
7). 偶数求平方,奇数求立方
常规写法
>>> lst = list(range(10))
>>> ret = []
>>> for x in lst:
... if x % 2 == 0:
... ret.append(x ** 2)
... else:
... ret.append(x ** 3)
...
>>> ret
[0, 1, 4, 27, 16, 125, 36, 343, 64, 729]
解析式的写法
>>> x = 3
>>> x ** 2 if x % 2 == 0 else x ** 3 这个是一个单独的程序,可以直接运行的
27
>>> ret = [x ** 2 if x % 2 == 0 else x ** 3 for x in lst] 结合上面的程序,就能实现“偶数求平方,奇数求立方”的解析式了
>>> ret
[0, 1, 4, 27, 16, 125, 36, 343, 64, 729]
列表解析式的优势
- 代码简洁,可读性强
- 效率比普通迭代稍高
列表解析式,对于性能的提升是微乎其微的,可以说,列表解析式就是为了代码的简洁,因此,我们在使用列表解析式的时候,一些复杂的循环或者判断操作,尽量不要使用列表解析式,因为那边不仅不会感觉出代码的简洁易懂,反而时间长了会自己都看不懂代码输出的结果是啥了。
生成器解析式
生成解析式返回的是一个生成器
列表解析式的中括号变成小括号,就是生成器解析式
>>> g = (x ** 2 for x in range(10000))
>>> next(g) 生成器是使用next逐条取值的
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
生成器解析式的好处:
- 当数据量大的时候,不会占用大量的内存
- 在取值的时候,才会计算
明确需要使用下标访问元素的时候,使用列表解析,当只需要对结果迭代的时候,优先使用生成器解析。
生成器解析式和列表解析式的使用格式是完全一样的,因此上面列表解析式的列举的所有例子,对于生成器解析同样适用
集合解析式
集合解析式返回的是一个集合
定义解析的时候,使用大括号定义,那么就是一个集合解析式了
>>> ret = {x for x in range(10)}
>>> ret
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> type(ret)
<class 'set'>
集合解析式和列表解析式的使用格式是完全一样的,因此上面列表解析式的列举的所有例子,对于集合解析同样适用
字典解析式
字典解析式返回的是一个字典
字典解析式的定义,也是使用大括号的,只不过是使用冒号来使用key->value的数据类型的
>>> ret = {str(x):x for x in range(10)}
>>> ret
{'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
也是和列表解析式的表现形式一样的