### 3.4.1 for 循环
最简单的循环是已知重复执行次数的循环。小学生经常有这样的“痛苦”时刻:因为一 个字(比如“烦”)写错了,被老师要求订正 10 遍。这时小学生没有捷径可走,只能在本子 上一遍一遍地写上 10 次。如果是命令计算机在屏幕上写 10 遍“烦”,是不是也只能用下面的 10 行指令来实现呢?
```
print "烦"
print "烦"
......
print "烦"
```
显然,这种做法非常烦琐,需要在键盘上敲很多键,而且不具有扩展性(抄写 1 万遍怎么办?)。本节介绍 Python 语言中的 for 语句,可以很好地解决上面这个问题。
for 语句的常用语法形式如下:
```
for <循环控制变量> in <序列>:
<循环体>
```
其语义是:用序列中的成员逐个赋值给循环控制变量,对每一次赋值都执行一遍循环体。当序列被遍历,即每一个值都用过了,则循环结束,控制转到下一条语句。注意,循环体部分 相对于 for 部分要左缩进。for 语句的执行流程如图 3.8(a)所示,或更常见地画成图 3.8(b) 的样子。
![](https://box.kancloud.cn/2016-02-22_56cafcddf1afd.png)
(a) (b)
图 3.8 for 循环的流程图
for 循环的循环次数显然是由序列中有多少成员(即序列长度)决定的,而循环控制变量 的作用是存储每一次循环所涉及的序列成员的信息。不难理解,循环控制变量的作用一般仅 仅限于这个循环语句,出了这个循环语句循环控制变量就失去了它的作用。因此,编程序时 最好用一个新变量来做循环控制变量,而不是用前面已经使用过的变量名,以便突显循环控 制变量专用于循环控制的角色,不引起理解上的混乱。
下面介绍利用 for 语句建立的几种常见循环模式。
计数器循环
我们可以用下面的 for 语句来解决将“烦”字显示 10 遍的问题:
```
>>> for i in range(10):
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
```
n = input("Input a number: ")
sum = 0
for i in range(1,n+1):
sum = sum + i*i
print "The result is:",sum
```
执行此程序,将得到如下输出:
```
>>> import eg3_9
Input a number: 100
The result is: 338350
```
遍历数据项列表
for 语句是针对任意序列进行遍历来建立循环的,并非只能与 range(10)之类的数字序列 搭配构成计数器循环。例如,下面的代码针对一个杂乱数据项构成的列表进行遍历:
```
>>> data = ['Born on:','July',2,2005]
>>> for d in data:
... print d,
...
Born on: July 2 2005
```
这里,数据列表的作用显然不是循环计数。当然,这种对数据列表的数据项进行遍历的 循环也可以转化成对数据列表的索引进行循环,代码如下:
```
>>> data = ['Born on:','July',2,2005]
>>> for i in range(len(data)):
print data[i],
Born on: July 2 2005
``` 显然这是不必要的。一般来说,直接对数据列表进行循环不但代码简单,执行效率也比针对 列表索引建立的循环要高。所以,如果没有必要,尽量不要使用 for 与 range 函数的搭配。
下面我们看一个最好用列表索引来建立循环的例子:假如我们希望对 data 列表间隔着访 问其成员(比如每次跳过两个成员),而不是顺序遍历列表,这时就可以用 range 函数来建立 索引。代码如下:
```
>>> data = ['Born on:','July',2,2005]
>>> for i in range(0,len(data),3):
print data[i],
Born on: 2005
```
遍历列表的同时修改列表
另一个常见的需要用序列索引来建立循环的情形是在遍历一个列表的同时要修改它,例
如:将列表中的每一个值都加 1。下面这个做法是错误的:
```
>>> data = [1,2,3,4,5]
>>> for x in data:
x = x + 1
>>> data
[1, 2, 3, 4, 5]
>>> x
6
```
原因是循环体中修改的是循环控制变量 x 而非列表 data。尽管 x 的值来自列表,但修改 x 的
值并不会导致该值的来源处发生改变。为了修改遍历的列表,可以使用列表索引来对列表的 相应位置赋值。代码如下:
```
>>> data = [1,2,3,4,5]
>>> for i in range(len(data)):
data[i] = data[i] + 1
>>> data
[2, 3, 4, 5, 6]
>>> i
6
```
遍历其他序列类型
回顾第 2 章的内容,序列是由若干数据项组成的一个有序的集合体,列表、字符串和元 组都是序列。前面的例子中所用的序列都是列表,下面通过例子演示利用字符串或元组建立 循环。先看针对字符串的 for 循环,其作用是将一个字符串的每个字符分拆显示:
```
>>> for c in "Hello World!":
print c,
H e l l o W o r l d !
```
可见,字符串其实就是一个字符序列,for 语句通过取遍字符串中的每一个字符来建立循环。 注意,如果 for 的循环体只有一行语句,那么可以直接跟在 for 那一行的冒号后面。还要注意 print 语句末尾的逗号,它使 print 不换行,从而让各字符显示在同一行上。
再看一个针对元组的 for 循环例子:
```
>>> for i in (1,2,3):
print i
1
2
3
```
可见,用于 for 循环时,元组和列表具有完全一样的作用。 我们还可以构造更复杂的嵌套结构的序列用于 for 循环,如元组的元组、元组的列表、
字符串的列表等等。以“元组的列表”为例,即列表中每个成员是元组。由于控制循环的循 环控制变量每次取序列中的一个成员作为值,所以这种情况下循环控制变量所取的值是元组。 例如:
```
>>> for t in [(1,2),(3,4),(5,6)]:
print t,t[0],t[1]
```
也可以用多个循环控制变量构成元组来建立 for 循环:
```
>>> for (x,y) in [(1,2),(3,4),(5,6)]:
print x,y
1 2
3 4
5 6
```
此例中,第一次循环时执行的赋值是(x,y) = (1,2),亦即 x 和 y 分别赋值 1 和 2。 最后看一个更复杂的序列:
```
>>> for ((a,b),c) in [([1,2],3),['XY',6]]:
print a,b,c
1 2 3
X Y 6
```
这个 for 语句的第一次循环相当于先执行了赋值:
```
((a,b),c) = ([1,2],3)
```
第二次循环相当于执行了赋值:
```
((a,b),c) = ['XY',6]
```
从此例可见,元组、列表、字符串三种序列类型是非常相似的,可以相互赋值。
- 前言
- 第 1 章 计算与计算思维
- 1.1 什么是计算?
- 1.1.1 计算机与计算
- 1.1.2 计算机语言
- 1.1.3 算法
- 1.1.4 实现
- 1.2 什么是计算思维?
- 1.2.1 计算思维的基本原则
- 1.2.2 计算思维的具体例子
- 1.2.3 日常生活中的计算思维
- 1.2.4 计算思维对其他学科的影响
- 1.3 初识 Python
- 1.3.1 Python 简介
- 1.3.2 第一个程序
- 1.3.3 程序的执行方式
- 1.3.4 Python 语言的基本成分
- 1.4 程序排错
- 1.5 练习
- 第 2 章 用数据表示现实世界
- 2.1 数据和数据类型
- 2.1.1 数据是对现实的抽象
- 2.1.1 常量与变量
- 2.1.2 数据类型
- 2.1.3 Python 的动态类型*
- 2.2 数值类型
- 2.2.1 整数类型 int
- 2.2.2 长整数类型 long
- 2.2.3 浮点数类型 float
- 2.2.4 数学库模块 math
- 2.2.5 复数类型 complex*
- 2.3 字符串类型 str
- 2.3.1 字符串类型的字面值形式
- 2.3.2 字符串类型的操作
- 2.3.3 字符的机内表示
- 2.3.4 字符串类型与其他类型的转换
- 2.3.5 字符串库 string
- 2.4 布尔类型 bool
- 2.4.1 关系运算
- 2.4.2 逻辑运算
- 2.4.3 布尔代数运算定律*
- 2.4.4 Python 中真假的表示与计算*
- 2.5 列表和元组类型
- 2.5.1 列表类型 list
- 2.5.2 元组类型 tuple
- 2.6 数据的输入和输出
- 2.6.1 数据的输入
- 2.6.2 数据的输出
- 2.6.3 格式化输出
- 2.7 编程案例:查找问题
- 2.8 练习
- 第 3 章 数据处理的流程控制
- 3.1 顺序控制结构
- 3.2 分支控制结构
- 3.2.1 单分支结构
- 3.2.2 两路分支结构
- 3.2.3 多路分支结构
- 3.3 异常处理
- 3.3.1 传统的错误检测方法
- 3.3.2 传统错误检测方法的缺点
- 3.3.3 异常处理机制
- 3.4 循环控制结构
- 3.4.1 for 循环
- 3.4.2 while 循环
- 3.4.3 循环的非正常中断
- 3.4.4 嵌套循环
- 3.5 结构化程序设计
- 3.5.1 程序开发过程
- 3.5.2 结构化程序设计的基本内容
- 3.6 编程案例:如何求 n 个数据的最大值?
- 3.6.1 几种解题策略
- 3.6.2 经验总结
- 3.7 Python 布尔表达式用作控制结构*
- 3.8 练习
- 第 4 章 模块化编程
- 4.1 模块化编程基本概念
- 4.1.1 模块化设计概述
- 4.1.2 模块化编程
- 4.1.3 编程语言对模块化编程的支持
- 4.2 Python 语言中的函数
- 4.2.1 用函数减少重复代码 首先看一个简单的用字符画一棵树的程序:
- 4.2.2 用函数改善程序结构
- 4.2.3 用函数增强程序的通用性
- 4.2.4 小结:函数的定义与调用
- 4.2.5 变量的作用域
- 4.2.6 函数的返回值
- 4.3 自顶向下设计
- 4.3.1 顶层设计
- 4.3.2 第二层设计
- 4.3.3 第三层设计
- 4.3.4 第四层设计
- 4.3.5 自底向上实现与单元测试
- 4.3.6 开发过程小结
- 4.4 Python 模块*
- 4.4.1 模块的创建和使用
- 4.4.2 Python 程序架构
- 4.4.3 标准库模块
- 4.4.4 模块的有条件执行
- 4.5 练习
- 第 5 章 图形编程
- 5.1 概述
- 5.1.1 计算可视化
- 5.1.2 图形是复杂数据
- 5.1.3 用对象表示复杂数据
- 5.2 Tkinter 图形编程
- 5.2.1 导入模块及创建根窗口
- 5.2.2 创建画布
- 5.2.3 在画布上绘图
- 5.2.4 图形的事件处理
- 5.3 编程案例
- 5.3.1 统计图表
- 5.3.2 计算机动画
- 5.4 软件的层次化设计:一个案例
- 5.4.1 层次化体系结构
- 5.4.2 案例:图形库 graphics
- 5.4.3 graphics 与面向对象
- 5.5 练习
- 第 6 章 大量数据的表示和处理
- 6.1 概述
- 6.2 有序的数据集合体
- 6.2.1 字符串
- 6.2.2 列表
- 6.2.3 元组
- 6.3 无序的数据集合体
- 6.3.1 集合
- 6.3.2 字典
- 6.4 文件
- 6.4.1 文件的基本概念
- 6.4.2 文件操作
- 6.4.3 编程案例:文本文件分析
- 6.4.4 缓冲
- 6.4.5 二进制文件与随机存取*
- 6.5 几种高级数据结构*
- 6.5.1 链表
- 6.5.2 堆栈
- 6.5.3 队列
- 6.6 练习
- 第 7 章 面向对象思想与编程
- 7.1 数据与操作:两种观点
- 7.1.1 面向过程观点
- 7.1.2 面向对象观点
- 7.1.3 类是类型概念的发展
- 7.2 面向对象编程
- 7.2.1 类的定义
- 7.2.2 对象的创建
- 7.2.3 对象方法的调用
- 7.2.4 编程实例:模拟炮弹飞行
- 7.2.5 类与模块化
- 7.2.6 对象的集合体
- 7.3 超类与子类*
- 7.3.1 继承
- 7.3.2 覆写
- 7.3.3 多态性
- 7.4 面向对象设计*
- 7.5 练习
- 第 8 章 图形用户界面
- 8.1 图形用户界面概述
- 8.1.1 程序的用户界面
- 8.1.2 图形界面的组成
- 8.1.3 事件驱动
- 8.2 GUI 编程
- 8.2.1 UI 编程概述
- 8.2.2 初识 Tkinter
- 8.2.3 常见 GUI 构件的用法
- 8.2.4 布局
- 8.2.5 对话框*
- 8.3 Tkinter 事件驱动编程
- 8.3.1 事件和事件对象
- 8.3.2 事件处理
- 8.4 模型-视图设计方法
- 8.4.1 将 GUI 应用程序封装成对象
- 8.4.2 模型与视图
- 8.4.3 编程案例:汇率换算器
- 8.5 练习
- 第 9 章 模拟与并发
- 9.1 模拟
- 9.1.1 计算机建模
- 9.1.2 随机问题的建模与模拟
- 9.1.3 编程案例:乒乓球比赛模拟
- 9.2 原型法
- 9.3 并行计算*
- 9.3.1 串行、并发与并行
- 9.3.2 进程与线程
- 9.3.3 多线程编程的应用
- 9.3.4 Python 多线程编程
- 9.3.5 小结
- 9.4 练习
- 第 10 章 算法设计和分析
- 10.1 枚举法
- 10.2 递归
- 10.3 分治法
- 10.4 贪心法
- 10.5 算法分析
- 10.5.1 算法复杂度
- 10.5.2 算法分析实例
- 10.6 不可计算的问题
- 10.7 练习
- 第 11 章 计算+X
- 11.1 计算数学
- 11.2 生物信息学
- 11.3 计算物理学
- 11.4 计算化学
- 11.5 计算经济学
- 11.6 练习
- 附录
- 1 Python 异常处理参考
- 2 Tkinter 画布方法
- 3 Tkinter 编程参考
- 3.1 构件属性值的设置
- 3.2 构件的标准属性
- 3.3 各种构件的属性
- 3.4 对话框
- 3.5 事件
- 参考文献