Lec 3 洪水填充和迷宫路径查找
1 一些有用的特性
1.1 内置函数zip
zip
是一个非常方便的Python内置函数,它使我们能够轻松地在多个可迭代对象中找到对应的元素。(“可迭代”意味着我们可以使用for循环来遍历它们的所有元素。)例如,考虑以下代码,它用于执行两个列表的元素级减法操作
def substract_lists(l1, l2):
assert len(l1) == len(l2)
out = []
for ix in range(len(l1)):
out.append(l1[ix] - l2[ix])
return out
我们可以使用Python内置函数zip以稍微不同的方式来解决这个问题。zip函数接受多个可迭代对象作为输入,并返回一个可以迭代的结构。在使用zip重写上面的subtract_lists之前,让我们先看一个小例子,以便熟悉zip函数
x = [100, 200, 300, 400]
y = [9, 8, 7, 6]
print(zip(x, y)) # prints <zip object at SOME_MEMORY_LOCATION>
这看起来本身并不是很有用,但zip对象的存在是为了被迭代。
for element in zip(x, y)
print(element)
### output
(100, 9)
(200, 8)
(300, 7)
(400, 6)
1.2 元组解包
zip
函数通常与另一个方便的 Python 特性结合使用:通过多重赋值为元组的每个元素命名
# example
i, j = (100, 9)
# 列表也是可以的
x, y, width, height = [0, 0, 100, 200]
如果右侧的元组或列表中的元素数量与左侧变量的数量不完全相同,则代码会引发错误。
由于 zip
函数创建元组,元组解包是为正在组合的列表的元素命名的方便方法。例如
for x_value, y_value in zip(x, y):
print(x_value, y_value)
我们重写上面列表减法的例子
"""
def substract_lists(l1, l2):
assert len(l1) == len(l2)
out = []
for ix in range(len(l1)):
out.append(l1[ix] - l2[ix])
return out
"""
# 重写后
def substract_lists(l1, l2):
assert len(l1) == len(l2)
out = []
for i, j in zip(l1, l2):
out.append(i - j)
return out
1.3)*
解包
我们还可以在调用函数时将元组或列表解包成其单独的元素。
get_pixel(image, row, col)
返回(row, col)位置的颜色。函数期望行和列作为单独的参数传递,但是我们的代码将处理由两个元素组成的 (row, col) 对,例如 location = (23, 11)。我们可以使用解包运算符 * 来提取对中的各个部分并将它们作为单独的参数传递
get_pixel(image, *location)
# 与下面的例子相同
get_pixel(image, localtion[0], location[1])
与元组解包类似,我们不仅可以在元组上使用这个运算符,还可以在列表上使用,而且元组或列表的长度可以是任意的。但是,如果长度不对,导致我们试图向函数传递错误数量的参数,那么 Python 就会引发错误。
1.4) 列表推导
我们想要根据其他列表的内容构建数据。比如 L=[9, 8, 7],我们想要建立一个新的列表,以L的奇数位数字加倍形成。
out = []
for num in L:
if num % 2 == 1: # if num is odd
out.append(num * 2)
可以写成
out = [number * 2 for number in L if number % 2 == 1]
而且支持将多个for循环放到列表推导式里面
out = []
for x in <sequence of x>:
if <condition on x>:
for y in <sequence of y>:
if <condition on y>
out.append(<some expression using x, y>)
可以改写成
[
<some expression using x, y>
for x in <sequence of x>
if <condition on x>
for y in <sequence of y>
<condition on y>
]
在列表推导中,if 后面可以跟 else 或 elif 吗,就像普通的 if 语句一样?事实证明答案是**否定的,因为这个 if 的目的是过滤结果列表——如果条件为真则产生一个元素,但如果条件为假则完全省略它。在需要 else 行为的情况下,您需要将它放在前导表达式中,使用 Python 的“一行 if”语法(也称为条件表达式或三元运算符):
[ <some expression> if <some_condition> else <other expression>
for x in <sequence of x> ]