本文主要介绍python语言特性中推导式语法,包括什么时候使用推导式,为什么使用推导式,列表推导式、元组推导式、集合推导式、字典推导式、以及多重推导式的写法
文章目录
- 引子:写法对比
- 为什么使用推导式
- 什么时候使用推导式
- 列表推导式
- 元组推导式
- 集合推导式
- 字典推导式
- 多重推导式/嵌套推导式
- 三重循环的推导式会写了吗?
"""
以下代码的功能是获取给定的数组中所有的偶数
"""
all_numbers = [1, 2, 3, 4, 5, 6, 7, 8]
# for循环写法
even_numbers = []
for number in all_numbers:
if number % 2 == 0:
even_numbers.append(number)
# 列表推导式写法
even_numbers = [number for number in all_numbers if number % 2 == 0]
上面两种的写法实现的功能是一致的。这意味着我们使用推导式的写法并不是出于功能需求,而是出于非功能需求,比如:代码更加易读、代码更加整洁等等。
重复执行某些操作
,代表的是"How",如果我们使用的是for循环的写法来获取所有的偶数,那么对于阅读代码的人来说,需要查看for循环中到底进行了哪些操作,才能够得出结论:这段代码取了给定的所有整数,并将偶数放到了新列表中
。变量名 = 推导式
,而赋值语句的意思是某个变量的值等于某个表达式/某个内容
,代表的是"What",所以如果我们使用的是推导式的写法,则对于阅读代码的人来说,这段代码的意思就是生成了某个内容,这个内容是给定所有整数中的所有偶数
。像上述引子中的情况一样,如果我们想要从当前的数据中重新生成满足某些条件的数据时,我们可以选择使用推导式。常见的比如:获取所有的奇数/偶数,生成所有数值的平方/某个计算结果,数据类型转换(列表转换成字典、字符串反序列化成python对象)等等
可以总结为两个要素:
如果涉及的处理逻辑比较复杂,需要将处理逻辑独立成一个函数,然后在推导式中调用。比如调用标准库json.loads来反序列化数据:
records: List[Dict] = [json.loads(json_content) for json_content in input_data]
明白了使用推导式的好处以及使用场景后,我们来介绍各个python原生容器类型的推导式如何写。
而介绍之后我们可以意识到各个容器类型的推导式语法基本一致,从中也可以看到python语法的简洁性和一致性。
列表的语法为: [process_logic(element) for element in container if conditon_is_met(element)]
列表推导式就是将for循环的循环体用中括号包裹起来,然后将for条件放在列表末尾,如下:
"""生成元素相同的新列表"""
>>> [n for n in [1, 2, 3]]
[1, 2, 3]
"""生成所有值是原值两倍的列表"""
>>> [n * 2 for n in [1, 2, 3]]
[2, 4, 6]
"""生成所有值是原值平方的列表"""
>>> [n**2 for n in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
"""获取原列表中所有的偶数"""
>>> [n for n in [1, 2, 3] if n % 2]
[1, 3]
将列表推导式的中括号改为小括号即可变成元组推导式。
但是,(expression code)
这个语法糖已经先被迭代器占用了,所以生成的其实是元组推导式对应的迭代器而不是元组。
如果要获得元组,需要用tuple()
方法进行转换:
"""查看小括号语法糖生成的对象类型"""
>>> print(type((number for number in range(10))))
<class 'generator'>
>>> print((number for number in range(10)))
<generator object <genexpr> at 0x00857F08>
"""转换成元组"""
>>> print(tuple((number for number in range(10))))
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
"""tuple()包括后, 内层的括号可以省略"""
>>> print(tuple(number for number in range(10)))
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
"""获取所有的偶数"""
>>> print(tuple(number for number in range(10) if number % 2 == 0))
(0, 2, 4, 6, 8)
集合推导式的写法,就是将列表推导式的中括号改为花括号即可,语法如下:
{process_logic(element) for element in container if conditon_is_met(element)}
例子如下:
"""生成所有元素的集合"""
>>> {s for s in [1, 2, 1, 0]}
set([0, 1, 2])
"""生成所有元素平方的集合"""
>>> {s**2 for s in [1, 2, 1, 0]}
set([0, 1, 4])
>>> {s**2 for s in range(10)}
set([0, 1, 4, 9, 16, 25, 36, 49, 64, 81])
"""生成所有奇数元素的集合"""
>>> {s for s in [1, 2, 3] if s % 2}
set([1, 3])
字典推导式和集合推导式相似,只是元素需要写成键值对(键: 值
)的形式,如下:
{key_logic(element): value_logic for element in container if conditon_is_met(element)}
例子如下:
"""从元素为二元组的列表生成字典"""
>>> {k: v for k, v in [(1, 2), (3, 4)]}
{1: 2, 3: 4}
"""从元素为二元组的元组生成字典"""
>>> {k: v for k, v in (('I', 1), ('II', 2))}
{'I': 1, 'II': 2}
"""从数值迭代器生成键等于值的字典"""
>>> {n: n for n in range(2)}
{0: 0, 1: 1}
"""生成键为ascii码字符, 值为对应ascii码值的字典"""
>>> {chr(n): n for n in (65, 66, 66)}
{'A': 65, 'B': 66}
"""将元素为二元组的元组中满足条件的所有元素转换成字典"""
>>> {k: v for k, v in (('a', 0), ('b', 1)) if v == 1}
{'b': 1}
其实就是多重循环如何改写成推导式的问题。写法也很简单,就是将多重循环按照外层到内层的顺序拼成一行,反正推导式内,如下:
[process(element_1, element_2) for element_1 in items_1 for element_2 in items_2]
等于以下多重循环的写法:
results = []
for element_1 in items_1:
for element_2 in items_2:
results.append(process(element_1, element_2))
例子如下:
"""
生成字符在前, 数值在后的组合
由于对字符的遍历在前, 所有字符相同的元素会聚在一起
"""
>>> [f"{char}{number}" for char in "ABCD" for number in range(4)]
['A0', 'A1', 'A2', 'A3', 'B0', 'B1', 'B2', 'B3', 'C0', 'C1', 'C2', 'C3', 'D0', 'D1', 'D2', 'D3']
"""
生成字符在前, 数值在后的组合
由于对数值的遍历在前, 所有数值相同的元素会聚在一起
"""
>>> [f"{char}{number}" for number in range(4) for char in "ABCD"]
['A0', 'B0', 'C0', 'D0', 'A1', 'B1', 'C1', 'D1', 'A2', 'B2', 'C2', 'D2', 'A3', 'B3', 'C3', 'D3']
"""生成二元组集合"""
>>> {(m, n) for n in range(2) for m in range(3, 5)}
set([(3, 0), (3, 1), (4, 0), (4, 1)])
>>> [f"{first}{second}{third}" for first in "AB" for second in range(2) for third in "XY"]
['A0X', 'A0Y', 'A1X', 'A1Y', 'B0X', 'B0Y', 'B1X', 'B1Y']
学会了吗?(●ˇ∀ˇ●)
好书推荐:
- 流畅的python
- Python编程 从入门到实践 第2版
- Python数据结构与算法分析 第2版
好课推荐:
- 零基础学python
- python核心技术与实战
- python自动化办公实战
写文不易,如果对你有帮助的话,来一波点赞、收藏、关注吧~