Python 3.3 教程 - 4 Python中的流程控制(未完成3.28更新)
?
原文请参见: http://docs.python.org/3/tutorial/controlflow.html
?
?
除了刚才介绍的while语句外,Python支持通常其它语言支持的流程控制语句,只是略有变动。
?
4.1 if语句
?
也许最有名的语句就是if语句了,比如:
?
?
>>> x = int(input("Please enter an integer: "))Please enter an integer: 42>>> if x < 0:... x = 0... print('Negative changed to zero')... elif x == 0:... print('Zero')... elif x == 1:... print('Single')... else:... print('More')...More
?
elif部分可有多个或没有,同时,else部分是可选的。关键字'elif'比'else if'要短很多,它可以避免过多的缩进。Python里面没有switch或者case这种语句,不过你可以使用if...elif...elif...来实现。
?
4.2 for语句
?
Python中的for语句和C或Pascal中的for有点不一样。Python中的for语句不像其它编程语言中for语句那样去遍历等差数列的数字(Pascal),或者用户定义一个结束条件和遍历的步数(C),Python的for语句用来遍历任意序列中的项(列表或者是字符串),以它们在序列中出现的次序进行遍历,比如:
?
?
>>> # Measure some strings:... words = ['cat', 'window', 'defenestrate']>>> for w in words:... print(w, len(w))...cat 3window 6defenestrate 12
?
如果你在遍历序列的循环中去修改这个序列的话,建议你可以先做一个序列的拷贝。遍历序列并不会隐式的产生一个拷贝。分片符使得这些操作异常的简单:
?
?
>>> for w in words[:]: # Loop over a slice copy of the entire list.... if len(w) > 6:... words.insert(0, w)...>>> words['defenestrate', 'cat', 'window', 'defenestrate']
?
4.3 range()函数
?
如果你需要遍历一连串数字的时候,你可以使用内建函数range(),它可以产生等差数列:
?
?
>>> for i in range(5):... print(i)...01234
?
生成的数字并不会包含给定的结尾数字,range(10)会产生10个数值,同时有10个合法的索引值。当然,你也可以让这个范围从另一个数字开始,或者指定一个其它的增量(或负增量,有些地方也叫步长):
?
?
range(5, 10) 5 through 9range(0, 10, 3) 0, 3, 6, 9range(-10, -100, -30) -10, -40, -70
?
为了遍历一个序列的索引,你可以结合使用range()和len():
?
?
>>> a = ['Mary', 'had', 'a', 'little', 'lamb']>>> for i in range(len(a)):... print(i, a[i])...0 Mary1 had2 a3 little4 lamb
?
在绝大多数场景中,建议使用更方便的enumerate(),详细信息请参考:Looping Techniques
?
当你打印一个range时,你会发现结果有点奇怪:
?
?
>>> print(range(10))range(0, 10)
?
我们感觉range()函数返回的对象的行为有点像列表,但实际上它只有在你遍历的时候会返回符合条件的序列项,但它并不会真正的产生一个列表,因此个函数是节省空间的。
?
我们称这种对象是可遍历的,在函数或者结构中可以使用这种对象获取符合条件的序列项直到条件不满足为止。我们已经看到for语句中是一种遍历,另外,list()函数是另一个例子,它会根据传入的可遍历对象来创建列表:
?
?
>>> list(range(5))[0, 1, 2, 3, 4]
?
稍后,我们将会看到更多的函数可以返回可遍历对象或者把可遍历对象作为参数。
?
?
?
4.4 break 和 continue语句,循环中的else块
?
break语句和C中的用法一样,用来跳出for或者是while循环。
?
在Python中,循环语句也可能有else语句块。循环中的else语句块是当循环正常结束之后才执行(访问的列表遍历到最后了,自定义条件为false了等等),如果是非正常结束的话就不会执行,比如循环中执行了break语句。请参看一下例子,该例子程序用来寻找素数:
?
?
>>> for n in range(2, 10):... for x in range(2, n):... if n % x == 0:... print(n, 'equals', x, '*', n//x)... break... else:... # loop fell through without finding a factor... print(n, 'is a prime number')...2 is a prime number3 is a prime number4 equals 2 * 25 is a prime number6 equals 2 * 37 is a prime number8 equals 2 * 49 equals 3 * 3
?
请注意,以上代码是正确的代码,其中else是属于for循环的,并不是属于if语句的。
?
else块使用在循环中时,有点像else使用在try语句块中:try语句的else块是在没有异常产生的时候才执行,循环的else语句块是在没有break产生的时候才执行。对于try语句的更多信息,请参考:Handling Exceptions
?
?Continue语句当然也和C语言中的一样了,用来在循环中继续执行下一趟遍历:
?
?
>>> for num in range(2, 10):... if num % 2 == 0:... print("Found an even number", num)... continue... print("Found a number", num)Found an even number 2Found a number 3Found an even number 4Found a number 5Found an even number 6Found a number 7Found an even number 8Found a number 9
?
?
4.5 pass语句
?
pass语句就是什么都不做。它可以在你不需要程序做什么事情,但是语法需要你做一些事情的时候来使用。比如:
?
?
>>> while True:... pass # Busy-wait for keyboard interrupt (Ctrl+C)...
?
?
该语句经常被用来创建最下的类:
?
?
>>> class MyEmptyClass:... pass...
?
?
另一个pass使用的地方是当你在设计新代码的时候它可以充当占位符的作用,允许你以一个非常抽象的层次上思考问题。比如:
?
?
>>> def initlog(*args):... pass # Remember to implement this!...
?
?
4.6 函数定义
?
?我们可以创建一个函数来实现Fabonacci序列以任意的数值为边界:
?
?
>>> def fib(n): # write Fibonacci series up to n... """Print a Fibonacci series up to n."""... a, b = 0, 1... while a < n:... print(a, end=' ')... a, b = b, a+b... print()...>>> # Now call the function we just defined:... fib(2000)0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
?
?
关键字def用来定义一个函数。在它后面必须紧跟函数名和括号括起的参数列表。同时,函数体从下一行开始,并且必须要缩进。
?
函数体的第一个语句可以是一个可选的字符串常量;该字符串常量是该函数的文档字符串,或者文档说明。有专门的工具可以自动的根据该文档字符串生成在线的文档或者是可打印的文档,再或者可以让用户在代码中互动的去浏览该说明。当你写代码的时候,包含一些文档说明是一个很好的习惯,你应该注意培养。
?
函数执行的时候会引入一个新的符号表来供函数的本地变量使用。更精确的讲,函数中所有的赋值变量被保存在本地符号表中;所以在引用变量的时候会先在本地符号表中进行查找,然后会在外围函数的本地符号表中查找,再然后才会在全局表中查找,最后则会在内建的变量表中查找。因此,全局的变量不能在函数中被直接赋值(除非你在一个global语句中命名),但是它们可以是被引用的。
?
在函数调用时的实际参数被保存到被调用函数的本地符号表中,因此,函数调用中的参数传递是一种传值的方式传递的。当一个函数调用另一个函数时,一个新的本地符号表将会创建。
?
函数定义的时候会在当前的符号表中引入函数的名字。函数的名字作为一个值的类型可以被解释器作为用户自定义的函数所识别。函数名字的值可以被赋值成其它的名字,赋值之后的名字也可以作为函数来使用。这作为一种通用的函数重命名机制:
?
?
>>> fib<function fib at 10042ed0>>>> f = fib>>> f(100)0 1 1 2 3 5 8 13 21 34 55 89
?
如果你学的是其它的语言,你可能会认为fib并不是一个函数,而是一个过程,因为它没有返回任何值。实际上,即便一个函数没有reture语句,它依然会返回一个值。这个值叫做None,它是一个内建的名字。你直接输入None通常解释器并不会显示它。当然,你可以通过print()语句来看到它的真正数值:
?
?
>>> fib(0)>>> print(fib(0))None
?
?
当然,如果你不想打印它,你也可以直接返回一个Fibonacci序列的列表:
?
?
>>> def fib2(n): # return Fibonacci series up to n... """Return a list containing the Fibonacci series up to n."""... result = []... a, b = 0, 1... while a < n:... result.append(a) # see below... a, b = b, a+b... return result...>>> f100 = fib2(100) # call it>>> f100 # write the result[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
?
以上的例子,证明了Python的一些新特性:
?
return语句会从函数中返回一个值。仅仅只有return的话会返回None.即便函数结尾没有return语句依然会返回None.语句result.append(a)调用了列表对象result的一个方法。(NF:就是对象调用方法的东西了,如果学Java的话很容易明白这个形式是在对象上执行方法。)?
?
4.7 函数定义中的更多内容
?
4.7.1 默认参数值
?
4.7.2 关键字参数
?
4.7.3 任意的参数列表
?
4.7.4 参数列表的解包
?
4.7.5 Lambda形式
?
4.7.6 文档字符串
?
4.7.7 函数注解
?
?
4.8 编码风格
?