β

《Python3.6官方文档》– 4.更多流程控制语句

并发编程网 – ifeve.com 14 阅读

4 更多流程控制语句

除了刚才介绍的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

if语句可以有零个或者更多 elif 分支, else 分支是非强制要求有的。关键词‘elif’是比‘else if’短的,这可以有效避免过度缩进问题。而且, if … elif … elif … 语句可以替换其它语言中的 switch/case 语句。

4.2. for Statements

Python中的for语句与你可能用过的C或者Pascal语言中的for语句有点不同。与通常通过一个等差数列进行迭代(像Pascal语言),或者给予用户自主迭代和终止步骤(就像C语言),Python的For语句以集合(list或者string)中的元素为迭代单元,按照它们在集合中的顺序逐个迭代。例如(我并没有含沙射影):

 >>> # Measure some strings:
 ... words = ['cat', 'window', 'defenestrate']
 >>> for w in words:
 ...     print(w, len(w))
 ...
 cat 3
 window 6
 defenestrate 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']

靠着使用 for w in words: 语法,我们可以用不断插入 defenestrate 单词,来尝试创建出很大的集合。

4.3. range()函数

如果你需要迭代一组连续数字,内建函数range()正好可以帮上忙。它生成递增数列:

  >>> for i in range(5):
  ...     print(i)
  ...





指定的尾数入参永远不是生成序列的一部分; range(10)生成十个数字,代表着会生成十个长度的序列。我们甚至可以让序列从另一个数字开始,或者指定另一个递增值(尽管被否认,但它有时被称为‘步长’):

  range(5, 10)
, 6, 7, 8, 9
  range(0, 10, 3)
, 3, 6, 9
  range(-10, -100, -30)
    -10, -40, -70

为了迭代集合的索引,我们可以把range()函数和len()函数结合起来使用。如下:

  >>> a = ['Mary', 'had', 'a', 'little', 'lamb']
  >>> for i in range(len(a)):
  ...     print(i, a[i])
  ...
 Mary
 had
 a
 little
 lamb

然而在大多数此类情况下,使用内置函数 enumerate() 更方便,参见 Looping Techniques章节

如果你打印一个range函数,会发生奇怪的事情:

  >>> print(range(10))
  range(0, 10)

从很多特性上看,rang()函数返回的对象都表现的像是一个list,但实际上它不是。当你迭代它时,它返回了你想要的连续数字,但是它为了节省内存空间,不是个真正的list。

我们称这种对象为可迭代的,即适合成为可以期待得到有限连续项的函数或者结构的目标。我们已经知道,for语句是一个类似的迭代器,list()函数也是一个类似的迭代器;它以可迭代对象创建list。

  >>> list(range(5))  
  [0, 1, 2, 3, 4] 

稍后我们可以看到更多函数可以返回可迭代对象,或者把可迭代对象作为入参。

4.4.循环中的break、continue语句和else子句

break语句,就像在C语言中一样,跳出最内层的for或者while循环。

循环语句也许有一个else子句;它在for语句的list循环终结时或者while语句的条件变为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')
  ...
 is a prime number
 is a prime number
 equals 2 * 2
 is a prime number
 equals 2 * 3
 is a prime number
 equals 2 * 4
 equals 3 * 3

(是的,这是一段没有错误的代码。仔细看:else子句是属于for循环,而不是if语句)

当与循环一起使用时,它的else子句与在try语句块和if语句块的else子句功能类似:当try语句块没有异常时,else分支触发执行;当循环没有被break终止时,else分支触发执行。想要学习更多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 2
  Found a number 3
  Found an even number 4
  Found a number 5
  Found an even number 6
  Found a number 7
  Found an even number 8
  Found a number 9

4.5. pass语句

pass语句什么也不执行。它可以背用于语法需要,但程序并不想执行任何任务。例如:

  >>> while True:
  ...     pass  # Busy-wait for keyboard interrupt (Ctrl+C)
  ...

它通常被用于创建一个最小的类:

  >>> class MyEmptyClass:
  ...     pass
  ...

另一个用处是,当你正在写新的代码,可以将pass写在函数体或者条件子句体中,用以标记占位,这使你在更抽象层面思考。pass会被自动忽略。

  >>> def initlog(*args):  
  ...     pass   # Remember to implement this!  
  ...  

4.6 函数定义

我们可以写一个可以输出不超过指定边界值的斐波那契数列的函数:

  >>> 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)
 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

关键词def定义了一个函数。它后边是函数名字和被括号包括起来的一串参数。函数体的声明是从下一行开始的,而且必须缩进。

函数体的第一行可以是一个随意的字符串数组;字符串数组是函数的文档字符串或者docstring。(更多关于docstring的说明可以在文档API部分找到)。有一些工具可以使用docstrings制作在线文档或者打印文档,或者让用户交互式的浏览代码;在代码中写入docstrings是一个很好的做法,你应该养成习惯。

函数执行时会为局部变量引入一个新的符号表。所有的局部变量都存储在这个局部符号表中。引用参数时,会先从局部符号表中查找,然后是全局符号表,然后是内置命名表。因此,全局参数虽然可以被引用,但它们不能在函数中直接赋值(除非它们在全局声明语句中)。

函数引用的实际参数在函数调用时引入局部符号表,因此,实参总是传值调用(这里的值指的是对象引用,而不是该对象的值)。[1] 一个函数被另一个函数调用时,一个新的局部符号表在调用过程中被创建。

函数的定义过程会在函数当前参数列表前定义函数名字。作为用户定义函数,函数名有一个为解释器认可的类型值。这个值可以赋给其它命名,使其能够作为一个函数来使用。这就像一个重命名机制:

  >>>
  >>> fib
  <function fib at 10042ed0>
  >>> f = fib
  >>> f(100)
 1 1 2 3 5 8 13 21 34 55 89

类比其它编程语言,你可能认为fib不是一个函数( function ),而是一个过程( procedure )。Python 和 C 一样,过程只是一个没有返回值的函数。实际上,没有显式声明返回值的过程也有一个返回值,虽然是一个不讨人喜欢的值。这个值被称为 None (这是一个内置命名)。如果一个值只是 None 的话,通常解释器不会写一个 None 出来,如果你真想要查看它的话,可以这样做:

  >>>
  >>> fib(0)
  >>> print(fib(0))
  None

我们来写一个简单的示例,用于演示如何从函数中返回一个包含菲波那契数列的数值链表,而不是打印它: 、

  >>>
  >>> 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 功能:

原创文章,转载请注明: 转载自 并发编程网 – ifeve.com 本文链接地址: 《Python3.6官方文档》– 4.更多流程控制语句


Favorite Loading 添加本文到我的收藏

Related posts:

  1. 《Python3.6官方文档》– 第十章
  2. 《Python3.6官方文档》14 章
  3. 《Python3.6官方文档》– 第一章
  4. 《Python3.6官方文档》– 第13章 接下来
  5. 《Python3.6官方文档》– 第十一章
  6. 《Python3.6官方文档》– 第二章 使用python解释器
  7. 《Python3.6官方文档》– 六月翻译邀请
  8. 《Python3.6官方文档》– 第12章 虚拟环境和包
  9. Java – 获取类中特定数据类型的字段
  10. 原子循环计数器
  11. 《Spring Data 官方文档》5.6 保存, 更新, 以及删除数据行
  12. Stackoverflow问答:Java是传值还是传引用?
  13. [Google Guava] 8-区间
  14. Fork/Join框架(三)加入任务的结果
  15. 话说模式匹配(5) for表达式中的模式匹配
作者:并发编程网 – ifeve.com
让天下没有难学的技术
原文地址:《Python3.6官方文档》– 4.更多流程控制语句, 感谢原作者分享。

发表评论