读书笔记-Python科学编程入门(A Primer on Scientific Programming with Python)(第五版)-第二章
第二章-循环和列表(Loops and Lists)
介绍两个循环语句:for 循环和 while 循环;介绍一种存储数据的对象(object):列表
2.1-While循环
用于重复执行若干条语句
- 结构为:
while 循环条件: 需循环的语句1 需循环的语句2 其他语句
- while 循环开始的标志:冒号(:)
- while 循环的循环体:相对 while 缩进一次的连续的若干行语句
- while 循环结束的标志:循环体后第一条与 while 平齐的语句(如上面的其他语句)
- while 循环过程:当满足循环条件时,执行循环体,直至循环条件不满足
- 例子:
print '------------------' # 表格开头 C = -20 # C的初始值 dC = 5 # 循环内C的增长值 while C <= 40: # 循环由一个循环条件开始 F = (9.0/5)*C + 32 # 第一条循环语句 print C, F # 第二条循环语句 C = C + dC # 第三条循环语句 print '------------------' # 表格结尾(在循环之后执行)
- 其结果为:
------------------ -20 -4.0 -15 5.0 -10 14.0 -5 23.0 0 32.0 5 41.0 10 50.0 15 59.0 20 68.0 25 77.0 30 86.0 35 95.0 40 104.0 ------------------
- 其目的:在 -20 到 40 间,以 5 为差值,将所有的摄氏温度转化为华氏温度,并将其打印出来
- 其中:
其为赋值语句。C 原先所指的 int 对象,在该语句执行后,自动被销毁;原因在于,该语句执行后,C 指向了新的对象(即等号右侧两式相加的和),导致原先的 int 对象没有任何变量指向它。(Before this assignment, C was already bound to an int object, and this object is automatically destroyed when C is bound to a new object and there are no other names (variables) referring to this previous object (if you did not get this last point, just relax and continue reading!).)C = C + dC
- 对这种类型的赋值语句有以下简写形式:
C += dC # 等价于 C = C + dC C -= dC # 等价于 C = C - dC C *= dC # 等价于 C = C*dC C /= dC # 等价于 C = C/dC
- 对于循环条件而言,根据判断结果,其结果为 True 或 False 中的一个
C == 40 # C 等于 40 C != 40 # C 不等于 40 C >= 40 # C 大于等于 40 C <= 40 # C 小于等于 40 C > 40 # C 大于 40 C < 40 # C 小于 40
类似的表达式称为逻辑表达式或布尔表达式(logical or boolean expressions)
- 在逻辑表达式前加 not,会使其值相反
C = 1 C == 40 # 结果为True not C == 40 # 结果为False
not C == 40 与 C != 40 等价,但更推荐后一种表达方式
- 逻辑表达式可由 and 或 or 相连,如:
while x > 0 and y <= 1: print x, y
其中,and 相连的逻辑表达式结果均为 True,结果才为 True;or 相连的逻辑表达式结果任意为 True,结果即为 True;其他情况均为 False
- 注意:
- 当 and 或 or 连接的是运算式时,返回的是其中的一个运算结果:
例如,(5 + 1) or -1 的值是 6; (5 + 1) and -1 的值是 -1
a 的结果 a and b a or b 0 / False 结果为 a 结果为 b 非0 / True 结果为 b 结果为 a - 对于各种对象而言,只要数字不为 0 或者字符串(string)、列表(list)、字典(dictionary)等不为空,结果均为Ture。例如:
>>> s = 'some string' >>> bool(s) True >>> s = '' # 空字符串 >>> bool(s) False
2.2-列表
2.2.1
列表:将数据按一定顺序保存起来
- 形如:
C = [-20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
其中,-20、 -15 等数据称为列表 C 的元素;列表的元素可以是任意对象;元素可以通过列表的索引(index)进行访问,索引从 0 开始计数,例如,C[2] 的返回值为 -10
- 列表的一些重要操作:
结构(Construction) 含义(Meaning) a = [] 初始化一个空列表 a = [1, 4.4, 'run.py'] 初始化一个列表 a.append(elem) 在列表的末尾添加一个元素 elem a + [1, 3] 两个列表相加 a.insert(i, e) 在当前索引为 i 的元素之前添加一个元素 e a[3] 索引为 3 的元素 a[-1] 倒数第 1 个元素 a[1:3] 切片(slice):从列表 a 索引为 1 的元素开始,到索引为 2 的所有元素,复制到一个子列表(sublist)中 del a[3] 删除索引为 3 的元素 a.remove(e) 删除值为 e 的元素 a.index('run.py') 找到值为 'run.py' 的元素的索引 'run.py' in a 检查列表是否包含该元素 a.count(v) 查看值为 v 的元素的总个数 len(a) 列表 a 包含的元素个数 min(a) 列表 a 中,值最小的元素 max(a) 列表 a 中,值最大的元素 sum(a) 将列表 a 中的所有元素相加 sorted(a) 返回顺序排序的列表 reversed(a) 返回倒序排序的列表 b[3][0][2] 返回嵌套列表的元素 isinstance(a, list) 如果 a 是列表,那么返回 True type(a) is list 如果 a 是列表,那么返回 True 其中,嵌套列表是元素为列表的列表;形如 len(a) 的表达式称为函数(function);在形如 a.append(elem) 的表达式中,称 append 是列表 a 的一个方法(method)
- 访问列表元素有两种方法:一种是通过索引来访问,例如 C[2];另一种访问方式依赖于列表的元素,例如:
>>> somelist = ['book.tex', 'book.log', 'book.pdf'] >>> texfile, logfile, pdf = somelist >>> texfile 'book.tex' >>> logfile 'book.log' >>> pdf 'book.pdf'
其中,第 2 行赋值语句左侧变量的个数要和列表的元素个数相同,否则会报错
2.2.2
for循环:遍历列表中的每个元素,每读取一个元素,进入一次循环体
- 结构为:
for 元素 in 列表: 循环体
- for 循环开始的标志、for 循环的循环体、for 循环结束的标志的表示与 while 循环一致
- for 循环过程:依次读取列表中的每个元素,每读取一个元素,进入一次循环体,直到所有元素被遍历完毕
- 例子:
degrees = [0, 10, 20, 40, 100] for C in degrees: print 'list element:', C print 'The degrees list has', len(degrees), 'elements'
- 其结果为:
list element: 0 list element: 10 list element: 20 list element: 40 list element: 100 The degrees list has 5 elements
- 其目的:依次读取列表 degrees 的元素,并将其打印出来;最后输出列表 degrees 的元素个数
2.3-列表和循环的选择性使用(Alternative Implementations with Lists and Loops)
2.3.1
for 循环和 while 循环可相互转化
- 两种等价的表达方式:
# 用 for 循环表示 for element in somelist: <process element> # 用 while 循环表示 index = 0 while index < len(somelist): element = somelist[index] <process element> index += 1
2.3.2
range 结构:按一定规则自动生成列表
- range(n) 生成列表 [0, 1, 2, ..., n-1]
- range(start, stop, step) 生成以 start 开头、前后元素相差 step 、元素值在 start 与 stop 间但不包括 stop 的列表。例如,range(2, 8, 3) 返回 [2, 5],range(1, 11, 2) 返回 [1, 3, 5, 7, 9]
- range(start, stop) 等价于 range(start, stop, 1)
2.3.3
for 循环遍历列表时的两种等价表达方式
- 两种等价的表达方式
# 直接访问 for element in somelist: ... # 通过索引访问 for i in range(len(somelist)): element = somelist[i] ...
推荐第一种表达方法,更为简练(which is more elegant to read)
- 生成列表时,还可以用 [i]*n 生成包含 n 个值为 i 的元素的列表;如 [0]*5 返回 [0, 0, 0, 0, 0]
2.3.4
修改列表元素时的注意事项
- 试图将每个元素均加上 5,可能会出现以下两种方法:
# 方法一 for c in Cdegrees: c += 5 # 方法二 for i in range(len(Cdegrees)): Cdegrees[i] += 5
方法一修改失败,而方法二修改成功。
- 方法一失败的原因:在方法一中,c += 5 操作结果,使 c 指向了新的浮点数对象 (c + 5),即只修改了 c 的值,但是对列表没有影响
- 方法二成功的原因:在方法二中,通过索引的直接访问,能直接修改列表的元素
- 可调用enumerate函数,同时访问索引和元素:
for i, c in enumerate(Cdegrees): Cdegrees[i] = c + 5
功能一致
2.3.5
列表推导(list comprehension):通过遍历已有的列表,导出新的列表
- 结构:
newlist = [E(e) for e in list]
其中,E(e) 表示包含元素 e 的表达式
2.3.6
同时遍历多个列表:两种方法
# 方法一 for i in range(len(Cdegrees)): print ’%5d %5.1f’ % (Cdegrees[i], Fdegrees[i]) # 方法二 for C, F in zip(Cdegrees, Fdegrees): print ’%5d %5.1f’ % (C, F)
推荐方法二;其中,zip 函数使 n 个列表 (list1, list2, list3, ...) 变为一个以 n 元组(n-tuples)为元素的列表,每个 n 元组 (e1, e2, e3, ...) 中的 e1、e2、e3、... 表示 list1、list2、list3、... 对应的元素,当列表的所有元组均被访问过后,for 循环停止
2.4-嵌套表(Nested Lists)
以列表为元素的列表
2.4.1
生成嵌套表
- 生成嵌套表的几种方法:
# 方法一 Cdegrees = range(-20, 41, 5) # -20, -15, ..., 35, 40 Fdegrees = [(9.0/5)*C + 32 for C in Cdegrees] table1 = [Cdegrees, Fdegrees] # 方法二 table2 = [] for C, F in zip(Cdegrees, Fdegrees): table2.append([C, F]) # 方法二的简写(利用列表推导) table2 = [[C, F] for C, F in zip(Cdegrees, Fdegrees)]
- 两种方法生成的嵌套表的结构分别如图所示:
![]()
- 嵌套表可通过索引直接访问:例如,table1[0][3] 返回 35
2.4.2
打印嵌套表
- 打印嵌套表的几种方法:
方法 特点 print table 输出很长的一行结果
import pprint
pprint.pprint(table)
结果过长的话,自动按元素换行 import scitools.pprint2
scitools.pprint2.pprint(table)
可通过 scitools.pprint2.float_format 控制输出格式,如通过 scitools.pprint2.float_format = ’%.2e’,使输出结果均以保留两位小数的科学计数法表示;默认的输出格式为 '%g'
存在舍入误差(round-off error)
for C, F in table:
print ’%5d %5.1f’ % (C, F)可自由地控制输出格式
2.4.3
提取原有列表的一部分,形成新列表;该部分称为子列表(sublist)或片段(slice)
- 提取子列表的几种方法:
结构 含义 A[i:] 提取 A 中 A[i] 之后(包括 A[i])的所有元素 A[:j] 提取 A 中 A[j] 之前(不包括 A[j])的所有元素 A[i:j] 提取 A 中 A[i] 之后(包括 A[i])、A[j] 之前(不包括 A[j])的所有元素
- 子列表是原列表的一个拷贝(copy),对原列表的任意操作,均不影响已经生成了的子列表
2.4.4
遍历嵌套表
- 当嵌套表内,每个列表元素的元素个数均相等时,可用以下方法遍历:
for C, F in table: # 遍历 C 和 F
若个数不同,则遍历次数由包含元素个数最少的列表元素决定
- 通过索引遍历
for p in range(len(scores)): for g in range(len(scores[p])): score = scores[p][g] print ’%4d’ % score, print
不大好,较难理解
- 通过元素遍历
for player in scores: for game in player: print ’%4d’ % game, print
很好,形象直观
2.5-元组(Tuples)
可看做是一种不可修改的列表
- 除了会修改元素的操作(比如:append,del,remove,index 和 sort)之外,列表的其他操作均适用于元组
- 与列表相比,元组的优势:
- 可保护元素不被篡改
- 基于元组的代码,比基于列表的代码更快
- 元组在 Python 软件中常被使用
- 元组可作为字典(dictionaries)的键值(keys),而列表不能 (详见第 6 章)
2.6-小结(Summary)
本章所学术语
- 列表(list)
- 元组(tuple)
- 嵌套列表(和嵌套元组)(nested list (and nested tuple))
- 子列表(子元组)(sublist (subtuple) or slice a[i:j])
- while 循环(while loop)
- for 循环(for loop)
- 列表推导(list comprehension)
- 布尔表达式(boolean expression)