5.3. 推导式进阶¶
进行多次赛选,选择出需要的值
[<i相关表达式> for i in aiterator if <条件> ]
{key_exp:value_exp for key_exp, value_exp in aiterator if <条件>}
5.3.1. 代码示例¶
#!/usr/bin/env python
#-*- coding:utf8 -*-
#获得一个1~10中所有数的平方,且平方值为偶数的一个列表
square_odd = [i**i for i in range(1,11) if i**i %2 == 1]
print(square_odd)
5.3.2. 1.编写推导式的两个“不要”¶
1.1 别写太复杂的推导式¶
比如,列表推导式的狂热爱好者很可能会写出下面这样的代码:
results = [
task.result if task.result_version == VERSION_2 else get_legacy_result(task)
for tasks_group in tasks
for task in in tasks_group
if task.is_active() and task.has_completed()
]
上面的表达式有两层嵌套循环,在获取任务结果部分还使用了一个三元表达式,读起来非常费劲。假如用原生循环代码来改写这段逻辑,代码量不见得会多出多少,但一定会更易读:
results = []
for tasks_group in tasks:
for task in tasks_group:
if not (task.is_active() and task.has_completed()):
continue
if task.result_version == VERSION_2:
result = task.result
else:
result = get_legacy_result(task)
results.append(result)
1.2 别把推导式当作代码量更少的循环¶
推导式是一种高度压缩的语法,这导致开发者有可能会把它当作一种更精简的循环来使用。比如在下面的代码里,我想要处理tasks列表里的所有任务,但其实并不关心process(task)的执行结果;为了节约代码量,我把代码写成了这样:
[ process(task) for task in tasks if not task.started ]
但这样做其实并不合适。推导式的核心意义在于它会返回值——一个全新构建的列表,如果你不需要这个新列表,就失去了使用表达式的意义。
直接编写循环并不会多出多少代码量,而且代码更直观:
for task in tasks:
if not task.started:
process(task)