Python 编写有Python特色的循环

Python 编写有Python特色的循环,对于有C语言风格背景的开发人员,若想知道他们是不是最近才使用Python,最简单的办法是观察他们如何编写循环。

例如,每当我看到类似下面的代码片段时,就知道有人试图用C或Java的风格编写Python代码:

my_items = ['a', 'b', 'c']

i = 0
while i < len(my_items):
    print(my_items[i])
    i += 1

这段代码看上去非常没有Python特色,有以下两点原因。
首先,代码中手动跟踪了索引i,先初始化将其置为零,然后在每次循环迭代时仔细递增索引。

其次,为了确定迭代次数,使用len()获取my_items容器的大小。

在Python中编写的循环会自动处理这两个问题,最好善加利用这一点。例如,如果代码不必跟踪正在运行的索引,那么就很难写出意外的无限循环,同时代码也更简洁、更可读。

下面来重构第一个代码示例,首先将删除用于手动更新索引的代码。在Python中可以用for循环来很好地做到这一点,做法是利用内置的range()自动生成索引:

>>> range(len(my_items))
range(0, 3)
>>> list(range(0, 3))
[0, 1, 2]

range类型表示不可变的数列,内存占用比普通列表少。range对象实际上并不存储数列的每个值,而是充当迭代器实时计算数列的值。

所以可以利用range()函数编写如下所示的内容,不用在每次循环迭代时手动递增i:

for i in range(len(my_items)):
    print(my_items[i])

比之前好一点,但仍然不是很有Python特色,感觉依然像是一个Java风格的迭代结构,而不是正常的Python循环。像range(len(...))这样的容器遍历方式通常可以进一步简化和改进它。

正如前面所提到的,在Python中,for循环实际上是for-each循环,可以直接在容器或序列中迭代元素,无须通过索引查找。因此可以用这一点来进一步简化:

for item in my_items:
    print(item)

这个解决方案很有Python特色,其中使用了几种Python高级特性,不过仍然非常整洁,看上去就像是在阅读编程教科书中的伪代码一样。注意循环中不再跟踪容器的大小,也不使用运行时索引来访问元素。

容器本身现在负责分发将要处理的元素。如果容器是有序的,那么所得到的元素序列也是有序的。如果容器是无序的,那么将以随机顺序返回其元素,但循环仍然会遍历所有元素。

当然,并不是所有情况下都能以这种方式重写循环。如果需要用到项的索引,该怎么办呢?

有一种方法既能让循环持有当前运行的索引,又能避免前面提到的range(len(...))模式。那就是使用内置的enumerate()改进这种循环,让其变得具有Python特色:

>>> for i, item in enumerate(my_items):
...     print(f'{i}: {item}')

0: a
1: b
2: c

看到没,Python中的迭代器可以连续返回多个值。迭代器可以返回含有任意个元素的元组,然后在for语句内解包。

这个功能非常强大,比如可以使用相同的技术同时迭代字典的键和值:

>>> emails = {
...     'Bob': 'bob@example.com',
...     'Alice': 'alice@example.com',
... }

>>> for name, email in emails.items():
...     print(f'{name} -> {email}')
'Bob -> bob@example.com'
'Alice -> alice@example.com'

还有一个例子,如果一定要编写一个C风格的循环,比如必须控制索引的步长,该怎么办呢?假如有下面这样的Java循环:

for (int i = a; i < n; i += s) {
    // ...
}

如何将这种模式转到Python中?这里要再次用到range()函数,该函数接受可选参数来控制循环的起始值(a)、终止值(n)和步长(s)。因此前面的Java循环示例可转换成下面这种Python形式:

for i in range(a, n, s):
    # ...

关键要点

  • 在Python中编写C风格的循环非常没有Python特色。要尽可能地避免手动管理循环索引和终止条件。

  • Python的for循环实际上是for-each循环,可直接在容器或序列中的元素上迭代。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程