第 3 章:运算符、表达式和程序流程¶
本章的重点是深入了解我们评估代码和编写有意义的条件逻辑块的每种方式。我们将介绍在 Python 表达式中使用的许多运算符的详细信息。本章还将涵盖一些已经在更详细的章节中讨论过的主题,例如循环结构和一些基本的程序流程。
我们将从讨论表达式的细节开始。如果你还记得第 1 章,表达式是一段代码,它会评估以产生一个值。我们在阅读前几章时已经看到了一些表达式在使用。在本章中,我们将更多地关注用于创建表达式的运算符的内部机制,以及我们可以使用的不同类型的表达式。本章将更详细地介绍如何定义用于循环和条件的代码块。
本章还将详细介绍如何编写和评估数学表达式和布尔表达式。最后但并非最不重要的一点是,我们将讨论如何使用增强赋值运算将两个或多个运算合并为一个。
表达式类型¶
Python 中的表达式是一段代码,它会产生一个结果或值。大多数情况下,我们认为表达式用于在我们的代码中执行数学运算。但是,还有许多用于其他目的的表达式。在第 2 章中,我们介绍了字符串操作、序列和字典操作的细节,并触及了使用集合。对这些对象执行的所有操作都是 Python 中的表达式形式。表达式的其他示例可能是调用方法或函数的代码片段,以及使用切片和索引操作列表。
数学运算¶
Python 包含所有基本的数学运算。本节将简要介绍每个运算符及其功能。你还会了解一些可以用于辅助数学表达式的内置函数。
假设这不是你学习的第一门编程语言,毫无疑问,你至少对在程序中执行数学运算有所了解。Python 在数学方面与其他编程语言没有什么不同,与大多数编程语言一样,执行数学计算和处理数字表达式非常简单。表 3-1 列出了数字运算符。
表 3-1. 数字运算符
运算符 | 描述 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
// | 截断除法 |
% | 取模(除法的余数) |
** | 幂运算符 |
+var | 一元加 |
-var | 一元减 |
表 3-1 中的大多数运算符的工作方式与您预期的一样,例如
清单 3-1. 数学运算符:
# Performing basic mathematical computations
>>> 10 - 6
4
>>> 9 * 7
63
但是,除法、截断除法、取模、幂运算和一元运算符可能需要一些解释。截断除法会自动将除法结果截断为整数,向下取整,取模运算会返回截断除法运算的余数。幂运算符的作用与您预期的一样,它返回运算符左侧数字乘以自身 n 次的结果,其中 n 代表运算符右侧的数字。
清单 3-2. 截断除法和幂运算:
>>> 36 // 5
7
# Modulo returns the remainder
>>> 36 % 5
1
# Using powers, in this case 5 to the power of 2
>>> 5**2
25
# 100 to the power of 2
>>> 100**2
10000
除法本身是一个有趣的话题,因为它目前的实现方式在某些情况下存在争议。问题 10/5 = 2 绝对成立。但是,在目前的实现中,除法以某种方式对数字进行舍入,有时会产生意外的结果。Jython 2.5 中提供了一种新的除法方法,可以通过从 __future__ 中导入来实现。在 2.5 及之前版本的标准除法中,返回的商是当参数为整数或长整数时商的向下取整(舍入后的最近整数)。但是,如果参数是浮点数或复数,则会返回除法的合理近似值。通常情况下,这种解决方案并非预期结果,因为商在任何情况下都应该是合理的近似值或“真除”。当我们从 __future__ 模块导入除法时,我们通过在使用 / 运算符时导致真除,而在使用 // 运算符时仅进行地板除法来改变除法的返回值。为了不破坏向后兼容性,开发人员将修复后的除法实现放在一个名为 __future__ 的模块中。__future__ 模块实际上包含旨在作为标准语言的一部分在未来某个版本中包含的代码。为了使用新的修复后的除法版本,重要的是您在使用除法之前始终从 __future__ 导入。看看下面的代码。
清单 3-3. 除法舍入问题:
# Works as expected
>>> 14/2
7
>>> 10/5
2
>>> 27/3
9
# Now divide some numbers that should result in decimals
# Here we would expect 1.5
>>> 3/2
1
# The following should give us 1.4
>>> 7/5
1
# In the following case, we'd expect 2.3333
>>> 14/6
2
如您所见,当我们期望看到小数时,我们实际上收到了一个整数值。原始除法实现的开发人员已经承认了这个问题,并使用新的 __future__ 实现修复了它。
清单 3-4. 使用 __future__ 除法:
# We first import division from __future__
from __future__ import division
# We then work with division as usual and see the expected results
>>> 14/2
7.0
>>> 10/5
2.0
>>> 27/3
9.0
>>> 3/2
1.5
>>> 7/5
1.4
>>> 14/6
2.3333333333333335
需要注意的是,Jython 实现与 CPython 有所不同,因为 Java 在某些情况下提供了额外的舍入。差异仅在于舍入的显示,因为 Jython 和 CPython 都使用相同的 IEEE 浮点数进行存储。让我们看看其中一个案例。
清单 3-5. Jython 和 CPython 除法之间的细微差别:
# CPython 2.5 Rounding
>>> 5.1/1
5.0999999999999996
# Jython 2.5
>>> 5.1/1
5.1
一元运算符可用于评估正数或负数。一元加运算符将数字乘以正 1(通常不会改变它),一元减运算符将数字乘以负 1。
清单 3-6. 一元运算符:
# Unary minus
>>> -10 + 5
-5
>>> +5 - 5
0
>>> -(1 + 2)
-3
如本节开头所述,有许多内置的数学函数供您使用。表 3-2 列出了内置的数学函数。
表 3-2. 数学内置函数
函数 | 描述 |
---|---|
abs(var) | 绝对值 |
pow(x, y) | 可以代替 ** 运算符使用 |
pow(x,y,modulo) | 三元幂取模(x**y)% 模数 |
round(var[, n]) | 返回舍入到最接近的 10-n 或 (10**-n) 的值,其中 n 默认值为 0) |
divmod(x, y) | 返回除法的商和余数的元组 |
清单 3-7. 数学内置函数:
# The following code provides some examples for using mathematical built-ins
# Absolute value of 9
>>> abs(9)
9
# Absolute value of -9
>>> abs(-9)
9
# Divide 8 by 4 and return quotient, remainder tuple
>>> divmod(8,4)
(2, 0)
# Do the same, but this time returning a remainder (modulo)
>>> divmod(8,3)
(2, 2)
# Obtain 8 to the power of 2
>>> pow(8,2)
64
# Obtain 8 to the power of 2 modulo 3 ((8 **2) % 3)
>>> pow(8,2,3)
1
# Perform rounding
>>> round(5.67,1)
5.7
>>> round(5.67)
6.00
比较运算符¶
比较运算符可用于比较两个或多个表达式或变量。与上面描述的数学运算符一样,这些运算符与 Java 没有显着差异。请参见表 3-3。
表 3-3. 比较运算符
运算符 | 描述 |
---|---|
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
!= | 不等于 |
== | 等于 |
清单 3-8. 比较运算符示例:
# Simple comparisons
>>> 8 > 10
False
>>> 256 < 725
True
>>> 10 == 10
True
# Use comparisons in an expression
>>> x = 2*8
>>> y = 2
>>> while x != y:
... print 'Doing some work...'
... y = y + 2
...
Doing some work...
Doing some work...
Doing some work...
Doing some work...
Doing some work...
Doing some work...
Doing some work...
# Combining comparisons
>>> 3<2<3
False
>>> 3<4<8
True
位运算符¶
Python 中的位运算符是一组用于以二进制补码方式处理数字的运算符。也就是说,在使用位运算符时,数字被视为由 0 和 1 组成的位串。如果您不熟悉二进制补码的概念,可以从维基百科页面开始了解:(http://en.wikipedia.org/wiki/Two’s_complement)。重要的是要知道位运算符只能应用于整数和长整数。让我们看一下可用的不同位运算符(表 3-4),然后我们将通过一些示例进行说明。
表 3-4. 位运算符
运算符 | 描述 |
---|---|
& | 按位与运算符将位复制到结果中,如果两个操作数中都出现了该位 |
| | 按位或运算符将位复制到结果中,如果它存在于任一操作数中 |
^ | 按位异或运算符将位复制到结果中,如果它仅存在于一个操作数中 |
~ | 按位取反运算符翻转位,并返回每个位的完全相反 |
假设我们有一些以二进制格式表示的数字,我们想使用位运算符对它们进行操作。让我们使用数字 14 和 27。数字 14 的二进制(二进制补码)表示为 00001110,而数字 27 的二进制表示为 00011011。位运算符查看数字的二进制格式中的每个 1 和 0,并执行它们各自的操作,然后返回结果。Python 不返回位,而是返回结果位的整数值。在以下示例中,我们取数字 14 和 27,并使用位运算符对它们进行操作。
清单 3-9. 位运算符示例:
>>> 14 & 27
10
>>> 14 | 27
31
>>> 14 ^ 27
21
>>> ~14
-15
>>> ~27
-28
为了总结上面的示例,让我们使用每个数字的二进制表示来完成操作。
14 & 27 = 00001110 and 00011011 = 00001010 (The integer 10)
14 | 27 = 00001110 or 000110011 = 00011111 (The integer 31)
14 ^ 27 = 00001110 xor 000110011 = 00010101 (The integer 21)
~14 = 00001110 = 11110001 (The integer -15)
移位运算符(参见表 3-5)类似,因为它们使用数字的二进制位表示。左移运算符将左操作数的值向左移动,移动的位数由右操作数指定。右移运算符执行完全相反的操作,它将左操作数的值向右移动,移动的位数由右操作数指定。本质上,这转化为左移运算符将左边的操作数乘以 2,乘以右操作数指定的次数。右移运算符的相反情况成立,它将左边的操作数除以 2,除以右操作数指定的次数。
表 3-5. 移位运算符
运算符 | 描述 |
---|---|
x << n | 左移(等效于将数字 x 乘以 2,n 次) |
x >> n | 右移(等效于将数字 x 除以 2,n 次) |
更准确地说,左移运算符 (<<) 将一个数字乘以 2,n 次,n 是移位运算符右边的数字。右移运算符将一个数字除以 2,n 次,n 是移位运算符右边的数字。__future__division 导入不会影响此类操作的结果。
清单 3-10. 移位运算符示例:
# Shift left, in this case 3*2
>>> 3<<1
6
# Equivalent of 3*2*2
>>> 3<<2
12
# Equivalent of 3*2*2*2*2*2
>>> 3<<5
96
# Shift right
# Equivalent of 3/2
>>> 3>>1
1
# Equivalent of 9/2
>>> 9>>1
4
# Equivalent of 10/2
>>> 10>>1
5
# Equivalent of 10/2/2
>>> 10>>2
2
虽然位运算符不是最常用的运算符,但它们值得掌握。如果您在数学情况下工作,它们尤其重要。
增强赋值¶
增强赋值运算符(参见表 3-6)将运算与赋值结合在一起。它们可以用来做一些事情,比如将一个变量赋值为它以前的值,并以某种方式进行修改。虽然增强赋值可以帮助简洁地编码,但有些人认为过多的此类运算符会使代码更难阅读。
清单 3-11. 增强赋值代码示例:
>>> x = 5
>>> x
5
# Add one to the value of x and then assign that value to x
>>> x+=1
>>> x
6
# Multiply the value of x by 5 and then assign that value to x
>>> x*=5
>>> x
30
表 3-6. 增强赋值运算符
运算符 | 等效 |
---|---|
a += b | a = a + b |
a -= b | a = a – b |
a *= b | a = a * b |
a /= b | a = a / b |
a %= b | a = a % b |
a //= b | a = a // b |
a **= b | a = a ** b |
a &= b | a = a & b |
a |= b | a = a | b |
a ^= b | a = a ^ b |
a >>= b | a = a >> b |
a <<= b | a = a << b |
布尔表达式¶
评估两个或多个值或表达式也使用与其他语言类似的语法,逻辑也基本相同。请注意,在 Python 中,True 和 False 与 Java 语言中的常量非常相似。True 实际上代表数字 1,False 代表数字 0。人们可以很容易地使用 0 和 1 来表示布尔值,但为了可读性和维护性,首选 True 和 False “常量”。Java 开发人员,请确保将这两个词的首字母大写,因为如果不这样做,您将收到一个难看的 NameError 错误。
布尔属性不仅限于处理 int 和 bool 值,它们还适用于其他值和对象。例如,在布尔表达式中简单地传递任何非空对象将在布尔上下文中评估为 True。这是一种确定字符串是否包含任何内容的好方法。请参见表 3-7。
清单 3-12。测试字符串:
>>> mystr = ''
>>> if mystr:
... 'Now I contain the following: %s' % (mystr)
... else:
... 'I do not contain anything'
...
'I do not contain anything'
>>> mystr = 'Now I have a value'
>>> if mystr:
... 'Now I contain the following: %s' % (mystr)
... else:
... 'I do not contain anything'
...
'Now I contain the following: Now I have a value'
表 3-7。布尔条件
条件 | 逻辑 |
---|---|
and | 在 x and y 评估中,如果 x 评估为 false,则返回其值,否则评估 y 并返回结果值 |
or | 在 x or y 评估中,如果 x 评估为 true,则返回其值,否则评估 y 并返回结果值 |
not | 在 not x 评估中,如果 not x,则表示 x 的相反 |
与所有编程语言一样,有一个运算符优先级来决定哪些运算符首先被评估。例如,如果我们有一个表达式 a + b * c,那么哪个运算会先执行?Python 的运算符优先级如表 3-8 所示,优先级最高的运算符排在最前面,优先级最低的运算符排在最后。相同运算符的重复从左到右分组,除了幂 (**) 运算符。
表 3-8。Python 运算符优先级从最高到最低
运算符 | 名称 |
---|---|
+var, -var, ~var | 一元运算 |
** | 幂运算 |
*, /, //, % | 乘法、除法、地板除法、取模 |
+, - | 加法、减法 |
<<, >> | 左移和右移 |
& | 按位与 |
^ | 按位异或 |
| | 按位或 |
<, >, <=. >= , <> | 比较运算符 |
==, != , is, is not, in, not in | 相等和成员资格 |
and, or, not | 布尔条件 |
需要注意的是,在处理布尔条件时,“and” 和 “or” 从左到右分组。让我们看几个例子。
清单 3-13。运算符优先级示例:
# Define a few variables
>>> x = 10
>>> y = 12
>>> z = 14
# (y*z) is evaluated first, then x is added
>>> x + y * z
178
# (x * y) is evaluated first, then z is subtracted from the result
>>> x * y - z
106
# When chaining comparisons, a logical 'and' is implied. In this
# case, x < y and y <= z and z > x
>>> x < y <= z > x
True
# (2 * 0) is evaluated first and since it is False or zero, it is returned
>>> 2 * 0 and 5 + 1
0
# (2 * 1) is evaluated first, and since it is True or not zero, the (5 + 1) is evaluated and
# returned
>>> 2 * 1 and 5 + 1
6
# x is returned if it is True, otherwise y is returned if it is False. If neither
# of those two conditions occur, then z is returned.
>>> x or (y and z)
10
# In this example, the (7 – 2) is evaluated and returned because of the 'and' 'or'
# logic
>>> 2 * 0 or ((6 + 8) and (7 - 2))
5
# In this case, the power operation is evaluated first, and then the addition
>>> 2 ** 2 + 8
12
转换¶
语言中内置了许多转换函数,以帮助将一种数据类型转换为另一种数据类型(参见表 3-9)。虽然 Jython 中的每种数据类型实际上都是一个类对象,但这些转换函数实际上会将一种类类型转换为另一种类类型。在大多数情况下,内置的转换函数很容易记住,因为它们主要以您尝试转换到的类型命名。
表 3-9。转换函数
函数 | 描述 |
---|---|
chr(value) | 将整数转换为字符 |
complex(real [,imag]) | 生成一个复数 |
dict(sequence) | 从给定的 (key, value) 元组序列生成字典 |
eval(string) | 评估字符串以返回一个对象……对数学计算很有用。注意:此函数应谨慎使用,因为它如果使用不当会造成安全隐患。 |
float(value) | 将数字转换为浮点数 |
frozenset(set) | 将集合转换为冻结集合 |
hex(value) | 将整数转换为表示该数字的十六进制字符串 |
int(value [, base]) | 如果给定字符串,则使用基数转换为整数 |
list(sequence) | 将给定序列转换为列表 |
long(value [, base]) | 如果给定字符串,则使用基数转换为长整数 |
oct(value) | 将整数转换为表示该数字的八进制字符串 |
ord(value) | 将字符转换为其整数值 |
repr(value) | 将对象转换为表达式字符串。与将表达式括在反引号中相同(x + y)。返回包含对象的可打印和可评估表示形式的字符串 |
set(sequence) | 将序列转换为集合 |
str(value) | 将对象转换为字符串 返回包含值的可打印表示形式的字符串,但不是可评估的字符串 |
tuple(sequence) | 将给定序列转换为元组 |
unichr(value) | 将整数转换为 Unicode 字符 |
清单 3-14. 转换函数示例:
# Return the character representation of the integers
>>> chr(4)
'\x04'
>>> chr(10)
'\n'
# Convert intger to float
>>> float(8)
8.0
# Convert character to its integer value
>>> ord('A')
65
>>> ord('C')
67
>>> ord('z')
122
# Use repr() with any object
>>> repr(3.14)
'3.14'
>>> x = 40 * 5
>>> y = 2**8
>>> repr((x, y, ('one','two','three')))
"(200, 256, ('one', 'two', 'three'))"
以下是使用 eval() 功能的示例,因为它可能是转换函数中唯一一个需要示例才能理解的函数。再次注意,如果使用不当,使用 eval() 函数可能很危险并构成安全威胁。如果使用 eval() 函数接受来自用户的文本,应设置标准安全预防措施以确保要评估的字符串不会危及安全。
清单 3-15. eval() 的示例:
# Suppose keyboard input contains an expression in string format (x * y)
>>> x = 5
>>> y = 12
>>> keyboardInput = 'x * y'
# We should provide some security checks on the keyboard input here to
# ensure that the string is safe for evaluation. Such a task is out of scope
# for this chapter, but it is good to note that comparisons on the keyboard
# input to check for possibly dangerous code should be performed prior to
# evaluation.
>>> eval(keyboardInput)
60
使用表达式控制程序流程¶
正如您在本手册之前参考中所了解的那样,构成 Python 程序的语句在结构上要注意间距、顺序和技术。每一段代码必须保持一致的间距,以便将每个控制结构与其他结构区分开来。Python 语法的最大优势之一是,一致的间距可以消除诸如大括号 {} 之类的分隔符。例如,在 Java 中,必须在 for 循环周围使用大括号来表示起点和终点。在 Python 中,只需正确地对 for 循环进行间距即可代替大括号。约定和最佳实践建议在整个程序中每条语句使用四个空格缩进。有关约定的更多信息,请参阅 PEP 8,Python 代码风格指南 (www.python.org/dev/peps/pep-0008/)。遵循此约定以及一些控制流程,您一定会开发出易于维护的软件。
if-elif-else 语句¶
标准 Python if-elif-else 条件语句用于评估表达式并根据结果分支程序逻辑。if-elif-else 语句可以包含我们之前讨论过的任何表达式。目标是编写和比较表达式,以便评估为 True 或 False 结果。如第 1 章所示,if-elif-else 语句的逻辑在表达式评估为 True 时遵循一条路径,或者在表达式评估为 False 时遵循另一条路径。
您可以根据需要将任意多个 if-else 表达式链接在一起。组合 if-else 关键字是 elif,它用于条件语句中第一个表达式和最后一个表达式之间的每个表达式。
elif 语句部分有助于确保程序逻辑的可读性。在彼此嵌套的太多 if 语句会导致难以维护的程序。首先评估初始 if 表达式,如果它评估为 False,则评估下一个 elif 表达式,如果它评估为 False,则继续该过程。如果任何 if 或 elif 表达式评估为 True,则处理该部分 if 语句中的语句。最终,如果所有表达式都评估为 False,则评估最终的 else 表达式。
以下示例展示了使用标准 if-elif-else 语句的几种方法。请注意,任何表达式都可以在 if-elif-else 结构中进行评估。这些只是一些简单的示例,但表达式内部的逻辑可以根据需要变得复杂。
清单 3-16. 标准 if-elif-else:
# terminal symbols are left out of this example so that you can see the precise indentation
pi =3.14
x = 2.7 * 1.45
if x == pi:
print 'The number is pi'
elif x > pi:
print 'The number is greater than pi'
else:
print 'The number is less than pi'
空列表或字符串也将被评估为 False,这使得它们易于在 if-elif-else 语句中用于比较目的。
清单 3-17. 评估空列表:
# Use an if-statement to determine whether a list is empty
# Suppose mylist is going to be a list of names
>>> mylist = []
>>> if mylist:
... for person in mylist:
... print person
... else:
... print 'The list is empty'
...
The list is empty
while 循环¶
我们在第 1 章中提到的另一个结构是循环。每种编程语言都提供循环实现,Python 也不例外。回顾一下,Python 语言提供了两种主要的循环类型,称为 while 循环和 for 循环。
while 循环逻辑遵循与 Java 中的 while 循环相同的语义。while 循环评估给定的表达式,并继续循环遍历其语句,直到表达式的结果不再成立并评估为 False。大多数 while 循环包含一个比较表达式,例如 x <= y 或类似的表达式,在这种情况下,当 x 大于 y 时,表达式将评估为 False。循环将继续处理,直到表达式评估为 False。此时循环结束,这就是 Java 实现的全部内容。另一方面,Python 允许使用 else 子句,该子句在循环完成后执行。
清单 3-18. Python while 语句:
>>> x = 0
>>> y = 10
>>> while x <= y:
... print 'The current value of x is: %d' % (x)
... x += 1
... else:
... print 'Processing Complete...'
...
The current value of x is: 0
The current value of x is: 1
The current value of x is: 2
The current value of x is: 3
The current value of x is: 4
The current value of x is: 5
The current value of x is: 6
The current value of x is: 7
The current value of x is: 8
The current value of x is: 9
The current value of x is: 10
Processing Complete...
此 else 子句在执行密集处理时非常有用,以便我们可以通知用户此类任务已完成。它在调试代码或在循环完成后需要进行某种清理时也很有用。
清单 3-19. 使用 with-else 重置计数器:
>>> total = 0
>>> x = 0
>>> y = 20
>>> while x <= y:
... total += x
... x += 1
... else:
... print total
... total = 0
...
210
continue 语句¶
当您处于循环结构中,并且需要告诉 Python 继续处理当前循环中剩余的语句时,应使用 continue 语句。一旦 Python 解释器看到 continue 语句,它就会结束当前循环的迭代,并继续处理下一个迭代。continue 语句可以与任何 for 或 while 循环一起使用。
清单 3-20. Continue 语句:
# Iterate over range and print out only the positive numbers
>>> x = 0
>>> while x < 10:
... x += 1
... if x % 2 != 0:
... continue
... print x
...
2
4
6
8
10
在此示例中,每当 x 为奇数时,‘continue’ 都会导致执行继续到循环的下一个迭代。当 x 为偶数时,它会被打印出来。
break 语句¶
与 continue 语句非常相似,break 语句可以在循环内部使用。我们使用 break 语句来完全停止循环,以便程序可以继续执行其下一个任务。这与 continue 不同,因为 continue 语句只停止当前循环的迭代,并继续进行下一个迭代。让我们来看看
清单 3-21. Break 语句:
>>> x = 10
>>> while True:
... if x == 0:
... print 'x is now equal to zero!'
... break
... if x % 2 == 0:
... print x
... x -= 1
...
10
8
6
4
2
x is now equal to zero!
在前面的示例中,循环终止条件始终为 True,因此只有在遇到 break 时,执行才会离开循环。如果我们正在使用一个位于另一个循环(嵌套循环结构)中的循环中的 break 语句,那么只有内部循环将被终止。
for 循环¶
for 循环可以用于任何可迭代对象。它将简单地遍历对象,并在每次传递期间执行一些处理。break 和 continue 语句也可以在 for 循环中使用。Python 中的 for 语句也与 Java 中的相同语句不同,因为在 Python 中,我们还有此结构的 else 子句。同样,当 for 循环在没有任何 break 干预或引发异常的情况下完成处理时,else 子句就会执行。此外,如果您熟悉 Java 5 之前的 for 循环,那么您会喜欢 Python 语法。在 Java 5 中,for 语句的语法略作调整,使其更符合 Python 等语法简单的语言。
清单 3-22. 比较 Java 和 Python for 循环
Java for 循环示例(Java 5 之前):
for (x = 0; x <= myList.size(); x++) {
// processing statements iterating through myList
System.out.println("The current index is: " + x);
}
清单 3-23. Python for 循环示例:
my_list = [1,2,3,4,5]
>>> for value in my_list:
... # processing statements using value as the current item in my_list
... print 'The current value is %s' % (value)
...
The current value is 1
The current value is 2
The current value is 3
The current value is 4
The current value is 5
正如您所见,Python 语法更容易理解,但在这一点上并没有真正节省太多按键。我们仍然需要自己管理索引(在本例中为 x),通过每次循环迭代递增它。但是,Python 提供了一个内置函数,可以为我们节省一些按键,并提供类似于 Java 在 for 循环中自动递增索引的功能。enumerate(sequence) 函数就是这样做的。它将为我们提供一个索引,并自动为我们管理它。
清单 3-24. enumerate() 功能:
>>> myList = ['jython','java','python','jruby','groovy']
>>> for index, value in enumerate(myList):
... print index, value
...
0 jython
1 java
2 python
3 jruby
4 groovy
如果我们不需要使用索引,可以将其删除,语法可以稍微清理一下。
>>> myList = ['jython', 'java', 'python', 'jruby', 'groovy']
>>> for item in myList:
... print item
...
jython
java
python
jruby
groovy
现在我们已经涵盖了 Python 语言中条件语句和循环结构的程序流程。但是,良好的编程实践会告诉您尽可能保持简单,否则逻辑将变得难以理解。在实践正确的编码技术时,还需要知道列表、字典和其他容器可以像其他对象一样进行迭代。使用 for 循环迭代容器是一种非常有用的策略。以下是如何迭代字典对象的示例。
清单 3-25. 迭代容器:
# Define a dictionary and then iterate over it to print each value
>>> my_dict = {'Jython':'Java', 'CPython':'C', 'IronPython':'.NET','PyPy':'Python'}
>>> for key in my_dict:
... print key
...
Jython
IronPython
CPython
PyPy
了解通过调用 my_dict.values() 可以通过每次迭代获取字典对象的 value 很有用。
示例代码¶
让我们看一个使用本章讨论的一些程序流程的示例程序。示例程序只是使用外部文本文件来管理运动队中的一系列球员。您将看到如何遵循正确的程序结构并在本示例中有效地使用空格。您还将看到文件利用的实际应用,以及 raw_input() 函数的利用。
清单 3-26. # 导入 os 模块:
import os
# Create empty dictionary
player_dict = {}
# Create an empty string
enter_player = ''
# Enter a loop to enter inforation from keyboard
while enter_player.upper() != 'X':
print 'Sports Team Administration App'
# If the file exists, then allow us to manage it, otherwise force creation.
if os.path.isfile('players.txt'):
enter_player = raw_input("Would you like to create a team or manage an existing team?\n (Enter 'C' for create, 'M' for manage, 'X' to exit) ")
else:
# Force creation of file if it does not yet exist.
enter_player = 'C'
# Check to determine which action to take. C = create, M = manage, X = Exit and Save
if enter_player.upper() == 'C':
# Enter a player for the team
print 'Enter a list of players on our team along with their position'
enter_cont = 'Y'
# While continuing to enter new player's, perform the following
while enter_cont.upper() == 'Y':
# Capture keyboard entry into name variable
name = raw_input('Enter players first name: ')
# Capture keyboard entry into position variable
position = raw_input('Enter players position: ')
# Assign position to a dictionary key of the player name
player_dict[name] = position
enter_cont = raw_input("Enter another player? (Press 'N' to exit or 'Y' to continue)")
else:
enter_player = 'X'
# Manage player.txt entries
elif enter_player.upper() == 'M':
# Read values from the external file into a dictionary object
print
print 'Manage the Team'
# Open file and assign to playerfile
playerfile = open('players.txt','r')
# Use the for-loop to iterate over the entries in the file
for player in playerfile:
# Split entries into key/value pairs and add to list
playerList = player.split(':')
# Build dictionary using list values from file
player_dict[playerList[0]] = playerList[1]
# Close the file
playerfile.close()
print 'Team Listing'
print '++++++++++++'
# Iterate over dictionary values and print key/value pairs
for i, player in enumerate(player_dict):
print 'Player %s Name: %s -- Position: %s' %(i, player, player_dict[player])
else:
# Save the external file and close resources
if player_dict:
print 'Saving Team Data...'
# Open the file
playerfile = open('players.txt','w')
# Write each dictionary element to the file
for player in player_dict:
playerfile.write('%s:%s\n' % (player.strip(),player_dict[player].strip()))
# Close file
playerfile.close()
此示例包含了前三章中讨论过的所有概念。如前所述,该概念是创建和管理一系列运动球员及其相对位置。示例从进入一个 while() 循环开始,该循环运行程序,直到用户输入退出命令。接下来,程序检查“players.txt”文件是否存在。如果存在,则程序提示用户输入代码以确定下一步要采取的操作。但是,如果文件不存在,则用户被迫在文件中至少创建一个球员/位置对。
继续,程序允许用户根据需要输入任意数量的球员/位置对,或随时退出程序。如果用户选择管理球员/位置列表,程序只需打开“players.txt”文件,使用 for() 循环迭代文件中的每个条目。字典在循环的每次迭代中都填充了当前球员。循环完成后,文件关闭,字典被迭代并打印。退出程序强制执行 else() 子句,该子句迭代字典中的每个球员并将它们写入文件。
不幸的是,这个程序非常简单,有些功能无法在没有函数(第 4 章)或类(第 6 章)知识的情况下实现。一个好的做法是在涵盖了这些主题后重新访问这个程序,并简化以及添加额外的功能。
总结¶
所有程序都是由语句和表达式构成的。在本章中,我们介绍了创建表达式和使用表达式的细节。表达式可以由任意数量的数学运算符和比较组成。在本章中,我们讨论了在程序中使用数学运算符的基础知识。__future__ 除法主题向我们介绍了如何使用 __future__ 中的功能。然后我们深入研究了比较和比较运算符。
本章最后讨论了正确的程序流程,并正确学习了 if 语句以及如何在 Python 中构建不同类型的循环。在下一章中,您将学习如何编写函数,并将讨论许多内置函数的使用。