3.4.1 for 循环

最简单的循环是已知重复执行次数的循环。小学生经常有这样的“痛苦”时刻:因为一 个字(比如“烦”)写错了,被老师要求订正 10 遍。这时小学生没有捷径可走,只能在本子 上一遍一遍地写上 10 次。如果是命令计算机在屏幕上写 10 遍“烦”,是不是也只能用下面的 10 行指令来实现呢?

  1. print "烦"
  2. print "烦"
  3. ......
  4. print "烦"

显然,这种做法非常烦琐,需要在键盘上敲很多键,而且不具有扩展性(抄写 1 万遍怎么办?)。本节介绍 Python 语言中的 for 语句,可以很好地解决上面这个问题。

for 语句的常用语法形式如下:

  1. for <循环控制变量> in <序列>:
  2. <循环体>

其语义是:用序列中的成员逐个赋值给循环控制变量,对每一次赋值都执行一遍循环体。当序列被遍历,即每一个值都用过了,则循环结束,控制转到下一条语句。注意,循环体部分 相对于 for 部分要左缩进。for 语句的执行流程如图 3.8(a)所示,或更常见地画成图 3.8(b) 的样子。

3.4.1 for 循环 - 图1

(a) (b)

图 3.8 for 循环的流程图

for 循环的循环次数显然是由序列中有多少成员(即序列长度)决定的,而循环控制变量 的作用是存储每一次循环所涉及的序列成员的信息。不难理解,循环控制变量的作用一般仅 仅限于这个循环语句,出了这个循环语句循环控制变量就失去了它的作用。因此,编程序时 最好用一个新变量来做循环控制变量,而不是用前面已经使用过的变量名,以便突显循环控 制变量专用于循环控制的角色,不引起理解上的混乱。

下面介绍利用 for 语句建立的几种常见循环模式。

计数器循环

我们可以用下面的 for 语句来解决将“烦”字显示 10 遍的问题:

  1. >>> for i in range(10):
  2. print "烦",

这条 for 语句的执行流程是这样的:计算 range(10)得到列表[0,1,2,3,4,5,6,7,8,9],然后令 变量 i 从左往右取遍列表[0, 1, … , 9]中的每一个值,并对所取的每个值都执行一次 print 语句。 由于列表有 10 个成员,故 print 就被执行了 10 次。注意 print 语句相对上面一行要缩进,表 示它是 for 循环要重复执行的语句。

在上面这个例子中,循环体与循环控制变量的值没有关系,即不管循环控制变量从序列 中取的值是什么,循环体总是固定地执行 print “烦”。从效果上看,循环控制变量和序列仅仅 起着计数器的作用,用于控制循环次数,这种循环模式称为计数器循环。

当然,循环体引用循环控制变量的值也是很常见的。这种情况下,循环控制变量不仅控 制循环次数,而且直接影响循环体的行为。例如,下面这个程序可以计算 1 到 n 的平方和:

【程序 3.9】eg3_9.py

  1. n = input("Input a number: ")
  2. sum = 0
  3. for i in range(1,n+1):
  4. sum = sum + i*i
  5. print "The result is:",sum

执行此程序,将得到如下输出:

  1. >>> import eg3_9
  2. Input a number: 100
  3. The result is: 338350

遍历数据项列表

for 语句是针对任意序列进行遍历来建立循环的,并非只能与 range(10)之类的数字序列 搭配构成计数器循环。例如,下面的代码针对一个杂乱数据项构成的列表进行遍历:

  1. >>> data = ['Born on:','July',2,2005]
  2. >>> for d in data:
  3. ... print d,
  4. ...
  5. Born on: July 2 2005

这里,数据列表的作用显然不是循环计数。当然,这种对数据列表的数据项进行遍历的 循环也可以转化成对数据列表的索引进行循环,代码如下:

  1. >>> data = ['Born on:','July',2,2005]
  2. >>> for i in range(len(data)):
  3. print data[i],
  4. Born on: July 2 2005
  5. ``` 显然这是不必要的。一般来说,直接对数据列表进行循环不但代码简单,执行效率也比针对 列表索引建立的循环要高。所以,如果没有必要,尽量不要使用 for 与 range 函数的搭配。
  6. 下面我们看一个最好用列表索引来建立循环的例子:假如我们希望对 data 列表间隔着访 问其成员(比如每次跳过两个成员),而不是顺序遍历列表,这时就可以用 range 函数来建立 索引。代码如下:

data = [‘Born on:’,’July’,2,2005] for i in range(0,len(data),3): print data[i], Born on: 2005 ```

遍历列表的同时修改列表

另一个常见的需要用序列索引来建立循环的情形是在遍历一个列表的同时要修改它,例

如:将列表中的每一个值都加 1。下面这个做法是错误的:

  1. >>> data = [1,2,3,4,5]
  2. >>> for x in data:
  3. x = x + 1
  4. >>> data
  5. [1, 2, 3, 4, 5]
  6. >>> x
  7. 6

原因是循环体中修改的是循环控制变量 x 而非列表 data。尽管 x 的值来自列表,但修改 x 的

值并不会导致该值的来源处发生改变。为了修改遍历的列表,可以使用列表索引来对列表的 相应位置赋值。代码如下:

  1. >>> data = [1,2,3,4,5]
  2. >>> for i in range(len(data)):
  3. data[i] = data[i] + 1
  4. >>> data
  5. [2, 3, 4, 5, 6]
  6. >>> i
  7. 6

遍历其他序列类型

回顾第 2 章的内容,序列是由若干数据项组成的一个有序的集合体,列表、字符串和元 组都是序列。前面的例子中所用的序列都是列表,下面通过例子演示利用字符串或元组建立 循环。先看针对字符串的 for 循环,其作用是将一个字符串的每个字符分拆显示:

  1. >>> for c in "Hello World!":
  2. print c,
  3. H e l l o W o r l d !

可见,字符串其实就是一个字符序列,for 语句通过取遍字符串中的每一个字符来建立循环。 注意,如果 for 的循环体只有一行语句,那么可以直接跟在 for 那一行的冒号后面。还要注意 print 语句末尾的逗号,它使 print 不换行,从而让各字符显示在同一行上。

再看一个针对元组的 for 循环例子:

  1. >>> for i in (1,2,3):
  2. print i
  3. 1
  4. 2
  5. 3

可见,用于 for 循环时,元组和列表具有完全一样的作用。 我们还可以构造更复杂的嵌套结构的序列用于 for 循环,如元组的元组、元组的列表、

字符串的列表等等。以“元组的列表”为例,即列表中每个成员是元组。由于控制循环的循 环控制变量每次取序列中的一个成员作为值,所以这种情况下循环控制变量所取的值是元组。 例如:

  1. >>> for t in [(1,2),(3,4),(5,6)]:
  2. print t,t[0],t[1]

也可以用多个循环控制变量构成元组来建立 for 循环:

  1. >>> for (x,y) in [(1,2),(3,4),(5,6)]:
  2. print x,y
  3. 1 2
  4. 3 4
  5. 5 6

此例中,第一次循环时执行的赋值是(x,y) = (1,2),亦即 x 和 y 分别赋值 1 和 2。 最后看一个更复杂的序列:

  1. >>> for ((a,b),c) in [([1,2],3),['XY',6]]:
  2. print a,b,c
  3. 1 2 3
  4. X Y 6

这个 for 语句的第一次循环相当于先执行了赋值:

  1. ((a,b),c) = ([1,2],3)

第二次循环相当于执行了赋值:

  1. ((a,b),c) = ['XY',6]

从此例可见,元组、列表、字符串三种序列类型是非常相似的,可以相互赋值。