读一读我——无废话Python(四)列表解析技巧(1)
假设现在你有个字典数据,keys 是网站的名称,values 是网站的点击量。你的任务是从中挑选出点击量大于 1000000 的网站,结果用 list 表示,里面存放的元素是 tuples,每个 tuple 里面有两个值,网站的名称和该网站的点击量,实现代码如下:
websites = {
'baidu': 1000000,
"google": 974560,
"bing": 1234589,
"qq": 896754,
"sina": 910745
}
result_websites = []
for k, v in websites.items():
if v > 1000000:
result_websites.append((k, v))
print(result_websites) # [('baidu', 1000000), ('bing', 1234589)]
假如我告诉你还有实现起来更简单,表达意图更明确,代码更可读的解决方案,该怎么做呢?
之前的文章讲过,Python 为创建 list 提供了更强力的方法:list comprehension(列表解析)。用法公式如下:
[ expression + context ]
公式中的中括号表明结果是个 list。context 表示的是我们要从哪个 list 中取数据,或者说是数据源;expression 表示的是如何对数据源中的数据进行操作,作为最后 list 中的元素。例子如下:
[x * 2 for x in range(3)]
上面例子的粗体部分就是 context,剩下的部分就是 expression。这个列表解析的意思就是,对一个 list,即 [0, 1, 2] 中的每个元素做 乘2 的操作后生成的新 list 作为结果返回。结果显而易见:[0, 2, 4]。
上面是最简单的使用形式,其实 expression 和 context 可以任意的复杂,例子是最好的解释说明:
print([❶ x ❷ for x in range(4)]) # [0, 1, 2, 3, 4]
❶ 恒等函数。为啥是个函数?你可以把 x 看成 x * 1。公式中这部分是 expression。
❷ context 中的变量 x 从 range 函数中取出所有值。
print([❶ (x, y) ❷ for x in range(2) for y in range(2)]) # [(0, 0), (0, 1), (1, 0), (1, 1)]
❶ 这个 expression 的结果是一个 tuple。tuple 中有两个值,也就说 context 需要提供给我们两个值。最后生成的 list 中的元素就是 tuple。
❷ 由于 expression 需要两个值,这两个值分别从两个内容一样的 list 中获取。实际上就是嵌套 for 循环给拉平了,请自行脑补。
print([❶ x ** 2 ❷ for x in range(10) if x % 2 > 0]) # [1, 9, 25, 49, 81]
❶ 对 context 中获取的数据做平方操作。
❷ 从 range(10) 中取值,但额外添加了限制条件,不能被 2 整除,也就是奇数。
print([❶ x.lower() ❷ for x in ["BAIDU", "GOOGLE", "BING"]]) # ["baidu", "google", "bing"]
❶ 对 context 取出的数据使用 lower 函数。
❷ 从一个包含全是大写字符串的 list 中取数据。
下面我们再来看看开头的需求如何用列表解析来实现。
websites = {
'baidu': 1000000,
"google": 974560,
"bing": 1234589,
"qq": 896754,
"sina": 910745
}
result_websites = [❶ (k, v) ❷ for k, v in websites.items() if v > 1000000]
print(result_websites) # 同开头结果 [('baidu', 1000000), ('bing', 1234589)]
❶ 需要 context 提供两个数据,并把它们变成 tuple 输出。
❷ 字典的 items 函数输出的是两个数据,分辨是字典的 key 和 value,并且在取出的 value 上做了限制,即 > 1000000。
这样的解决方案是不是更 pythonic 呢?
请关注公众号“读一读我”