4. 其他流程控制工具
*******************

Besides the "while" statement just introduced, Python uses the usual
flow control statements known from other languages, with some twists.


4.1. "if" Statements
====================

可能最为人所熟知的编程语句就是 "if" 语句了。例如：

   >>> x = int(raw_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

There can be zero or more "elif" parts, and the "else" part is
optional.  The keyword ‘"elif"’ is short for ‘else if’, and is useful
to avoid excessive indentation.  An  "if" … "elif" … "elif" … sequence
is a substitute for the "switch" or "case" statements found in other
languages.


4.2. "for" Statements
=====================

The "for" statement in Python differs a bit from what you may be used
to in C or Pascal.  Rather than always iterating over an arithmetic
progression of numbers (like in Pascal), or giving the user the
ability to define both the iteration step and halting condition (as
C), Python’s "for" statement iterates over the items of any sequence
(a list or a string), in the order that they appear in the sequence.
For example (no pun intended):

   >>> # Measure some strings:
   ... words = ['cat', 'window', 'defenestrate']
   >>> for w in words:
   ...     print w, len(w)
   ...
   cat 3
   window 6
   defenestrate 12

If you need to modify the sequence you are iterating over while inside
the loop (for example to duplicate selected items), it is recommended
that you first make a copy.  Iterating over a sequence does not
implicitly make a copy.  The slice notation makes this especially
convenient:

   >>> 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()" 函数
===================

If you do need to iterate over a sequence of numbers, the built-in
function "range()" comes in handy.  It generates lists containing
arithmetic progressions:

   >>> range(10)
   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

The given end point is never part of the generated list; "range(10)"
generates a list of 10 values, the legal indices for items of a
sequence of length 10.  It is possible to let the range start at
another number, or to specify a different increment (even negative;
sometimes this is called the ‘step’):

   >>> range(5, 10)
   [5, 6, 7, 8, 9]
   >>> range(0, 10, 3)
   [0, 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]
   ...
   0 Mary
   1 had
   2 a
   3 little
   4 lamb

然而，在大多数这类情况下，使用 "enumerate()" 函数比较方便，请参见 循环
的技巧 。


4.4. "break" and "continue" Statements, and "else" Clauses on Loops
===================================================================

"break" 语句，和 C 中的类似，用于跳出最近的 "for" 或 "while" 循环.

Loop statements may have an "else" clause; it is executed when the
loop terminates through exhaustion of the list (with "for") or when
the condition becomes false (with "while"), but not when the loop is
terminated by a "break" statement.  This is exemplified by the
following loop, which searches for prime numbers:

   >>> 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 number
   3 is a prime number
   4 equals 2 * 2
   5 is a prime number
   6 equals 2 * 3
   7 is a prime number
   8 equals 2 * 4
   9 equals 3 * 3

（是的，这是正确的代码。仔细看： "else" 子句属于 "for" 循环， **不属于
** "if" 语句。）

When used with a loop, the "else" clause has more in common with the
"else" clause of a "try" statement than it does that of "if"
statements: a "try" statement’s "else" clause runs when no exception
occurs, and a loop’s "else" clause runs when no "break" occurs. For
more on the "try" statement and exceptions, see 处理异常.

"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" Statements
======================

"pass" 语句什么也不做。当语法上需要一个语句，但程序需要什么动作也不做
时，可以使用它。例如:

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

这通常用于创建最小的类:

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

Another place "pass" can be used is as a place-holder for a function
or conditional body when you are working on new code, allowing you to
keep thinking at a more abstract level.  The "pass" is silently
ignored:

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


4.6. 定义函数
=============

我们可以创建一个输出任意范围内 Fibonacci 数列的函数:

   >>> 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,
   ...         a, b = b, a+b
   ...
   >>> # 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" 引入一个函数 *定义*。它必须后跟函数名称和带括号的形式参数
列表。构成函数体的语句从下一行开始，并且必须缩进。

函数体的第一个语句可以（可选的）是字符串文字；这个字符串文字是函数的文
档字符串或 *docstring* 。（有关文档字符串的更多信息，请参阅  文档字符
串 部分）有些工具使用文档字符串自动生成在线或印刷文档，或者让用户以交
互式的形式浏览代码；在你编写的代码中包含文档字符串是一种很好的做法，所
以要养成习惯。

The *execution* of a function introduces a new symbol table used for
the local variables of the function.  More precisely, all variable
assignments in a function store the value in the local symbol table;
whereas variable references first look in the local symbol table, then
in the local symbol tables of enclosing functions, then in the global
symbol table, and finally in the table of built-in names. Thus, global
variables cannot be directly assigned a value within a function
(unless named in a "global" statement), although they may be
referenced.

在函数被调用时，实际参数（实参）会被引入被调用函数的本地符号表中；因此
，实参是通过 *按值调用* 传递的（其中 *值* 始终是对象 *引用* 而不是对象
的值）。[1] 当一个函数调用另外一个函数时，将会为该调用创建一个新的本地
符号表。

函数定义会把函数名引入当前的符号表中。函数名称的值具有解释器将其识别为
用户定义函数的类型。这个值可以分配给另一个名称，该名称也可以作为一个函
数使用。这用作一般的重命名机制:

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

Coming from other languages, you might object that "fib" is not a
function but a procedure since it doesn’t return a value.  In fact,
even functions without a "return" statement do return a value, albeit
a rather boring one.  This value is called "None" (it’s a built-in
name).  Writing the value "None" is normally suppressed by the
interpreter if it would be the only value written. You can see it if
you really want to using "print":

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

* The "return" statement returns with a value from a function.
  "return" without an expression argument returns "None". Falling off
  the end of a function also returns "None".

* "result.append(a)" 语句调用了列表对象 "result" 的 *方法* 。方法是“
  属 于”一个对象的函数，它被命名为 "obj.methodname" ，其中 "obj" 是某
  个对 象（也可能是一个表达式）， "methodname" 是由对象类型中定义的方
  法的名 称。不同的类型可以定义不同的方法。不同类型的方法可以有相同的
  名称而不 会引起歧义。（可以使用 *类* 定义自己的对象类型和方法，请参
  阅 类 ）示 例中的方法 "append()" 是为列表对象定义的；它会在列表的最
  后添加一个新 的元素。在这个示例中它相当于 "result = result + [a]" ，
  但更高效。


4.7. 函数定义的更多形式
=======================

给函数定义有可变数目的参数也是可行的。这里有三种形式，可以组合使用。


4.7.1. 参数默认值
-----------------

最有用的形式是对一个或多个参数指定一个默认值。这样创建的函数，可以用比
定义时允许的更少的参数调用，比如:

   def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
       while True:
           ok = raw_input(prompt)
           if ok in ('y', 'ye', 'yes'):
               return True
           if ok in ('n', 'no', 'nop', 'nope'):
               return False
           retries = retries - 1
           if retries < 0:
               raise IOError('refusenik user')
           print complaint

这个函数可以通过几种方式调用:

* 只给出必需的参数："ask_ok('Do you really want to quit?')"

* 给出一个可选的参数："ask_ok('OK to overwrite the file?', 2)"

* 或者给出所有的参数："ask_ok('OK to overwrite the file?', 2, 'Come
  on, only yes or no!')"

这个示例还介绍了 "in" 关键字。它可以测试一个序列是否包含某个值。

默认值是在 *定义过程* 中在函数定义处计算的，所以

   i = 5

   def f(arg=i):
       print arg

   i = 6
   f()

会打印 "5"。

**重要警告：** 默认值只会执行一次。这条规则在默认值为可变对象（列表、
字典以及大多数类实例）时很重要。比如，下面的函数会存储在后续调用中传递
给它的参数:

   def f(a, L=[]):
       L.append(a)
       return L

   print f(1)
   print f(2)
   print f(3)

这将打印出

   [1]
   [1, 2]
   [1, 2, 3]

如果你不想要在后续调用之间共享默认值，你可以这样写这个函数:

   def f(a, L=None):
       if L is None:
           L = []
       L.append(a)
       return L


4.7.2. 关键字参数
-----------------

也可以使用形如 "kwarg=value" 的 *关键字参数* 来调用函数。例如下面的函
数:

   def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
       print "-- This parrot wouldn't", action,
       print "if you put", voltage, "volts through it."
       print "-- Lovely plumage, the", type
       print "-- It's", state, "!"

接受一个必需的参数（"voltage"）和三个可选的参数（"state", "action"，和
"type"）。这个函数可以通过下面的任何一种方式调用:

   parrot(1000)                                          # 1 positional argument
   parrot(voltage=1000)                                  # 1 keyword argument
   parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
   parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
   parrot('a million', 'bereft of life', 'jump')         # 3 positional arguments
   parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword

但下面的函数调用都是无效的:

   parrot()                     # required argument missing
   parrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argument
   parrot(110, voltage=220)     # duplicate value for the same argument
   parrot(actor='John Cleese')  # unknown keyword argument

在函数调用中，关键字参数必须跟随在位置参数的后面。传递的所有关键字参数
必须与函数接受的其中一个参数匹配（比如 "actor" 不是函数 "parrot" 的有
效参数），它们的顺序并不重要。这也包括非可选参数，（比如
"parrot(voltage=1000)" 也是有效的）。不能对同一个参数多次赋值。下面是
一个因为此限制而失败的例子:

   >>> def function(a):
   ...     pass
   ...
   >>> function(0, a=0)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: function() got multiple values for keyword argument 'a'

When a final formal parameter of the form "**name" is present, it
receives a dictionary (see 映射类型 — dict) containing all keyword
arguments except for those corresponding to a formal parameter.  This
may be combined with a formal parameter of the form "*name" (described
in the next subsection) which receives a tuple containing the
positional arguments beyond the formal parameter list.  ("*name" must
occur before "**name".) For example, if we define a function like
this:

   def cheeseshop(kind, *arguments, **keywords):
       print "-- Do you have any", kind, "?"
       print "-- I'm sorry, we're all out of", kind
       for arg in arguments:
           print arg
       print "-" * 40
       keys = sorted(keywords.keys())
       for kw in keys:
           print kw, ":", keywords[kw]

它可以像这样调用:

   cheeseshop("Limburger", "It's very runny, sir.",
              "It's really very, VERY runny, sir.",
              shopkeeper='Michael Palin',
              client="John Cleese",
              sketch="Cheese Shop Sketch")

当然它会打印:

   -- Do you have any Limburger ?
   -- I'm sorry, we're all out of Limburger
   It's very runny, sir.
   It's really very, VERY runny, sir.
   ----------------------------------------
   client : John Cleese
   shopkeeper : Michael Palin
   sketch : Cheese Shop Sketch

Note that the list of keyword argument names is created by sorting the
result of the keywords dictionary’s "keys()" method before printing
its contents; if this is not done, the order in which the arguments
are printed is undefined.


4.7.3. 任意的参数列表
---------------------

最后，最不常用的选项是可以使用任意数量的参数调用函数。这些参数会被包含
在一个元组里（参见 元组和序列 ）。在可变数量的参数之前，可能会出现零个
或多个普通参数。:

   def write_multiple_items(file, separator, *args):
       file.write(separator.join(args))


4.7.4. 解包参数列表
-------------------

当参数已经在列表或元组中但要为需要单独位置参数的函数调用解包时，会发生
相反的情况。例如，内置的 "range()" 函数需要单独的 *start* 和 *stop* 参
数。如果它们不能单独使用，可以使用 "*"-操作符 来编写函数调用以便从列表
或元组中解包参数:

   >>> range(3, 6)             # normal call with separate arguments
   [3, 4, 5]
   >>> args = [3, 6]
   >>> range(*args)            # call with arguments unpacked from a list
   [3, 4, 5]

同样的方式，字典可使用 "**" 操作符 来提供关键字参数:

   >>> def parrot(voltage, state='a stiff', action='voom'):
   ...     print "-- This parrot wouldn't", action,
   ...     print "if you put", voltage, "volts through it.",
   ...     print "E's", state, "!"
   ...
   >>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
   >>> parrot(**d)
   -- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !


4.7.5. Lambda 表达式
--------------------

可以用 "lambda" 关键字来创建一个小的匿名函数。这个函数返回两个参数的和
： "lambda a, b: a+b" 。Lambda函数可以在需要函数对象的任何地方使用。它
们在语法上限于单个表达式。从语义上来说，它们只是正常函数定义的语法糖。
与嵌套函数定义一样，lambda函数可以引用包含范围的变量:

   >>> def make_incrementor(n):
   ...     return lambda x: x + n
   ...
   >>> f = make_incrementor(42)
   >>> f(0)
   42
   >>> f(1)
   43

上面的例子使用一个lambda表达式来返回一个函数。另一个用法是传递一个小函
数作为参数:

   >>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
   >>> pairs.sort(key=lambda pair: pair[1])
   >>> pairs
   [(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]


4.7.6. 文档字符串
-----------------

There are emerging conventions about the content and formatting of
documentation strings.

第一行应该是对象目的的简要概述。为简洁起见，它不应显式声明对象的名称或
类型，因为这些可通过其他方式获得（除非名称恰好是描述函数操作的动词）。
这一行应以大写字母开头，以句点结尾。

如果文档字符串中有更多行，则第二行应为空白，从而在视觉上将摘要与其余描
述分开。后面几行应该是一个或多个段落，描述对象的调用约定，它的副作用等
。

Python解析器不会从Python中删除多行字符串文字的缩进，因此处理文档的工具
必须在需要时删除缩进。这是使用以下约定完成的。文档字符串第一行 *之后*
的第一个非空行确定整个文档字符串的缩进量。（我们不能使用第一行，因为它
通常与字符串的开头引号相邻，因此它的缩进在字符串文字中不明显。）然后从
字符串的所有行的开头剥离与该缩进 “等效” 的空格。 缩进的行不应该出现，
但是如果它们出现，则应该剥离它们的所有前导空格。应在扩展标签后测试空白
的等效性（通常为8个空格）。

下面是一个多行文档字符串的例子:

   >>> def my_function():
   ...     """Do nothing, but document it.
   ...
   ...     No, really, it doesn't do anything.
   ...     """
   ...     pass
   ...
   >>> print my_function.__doc__
   Do nothing, but document it.

       No, really, it doesn't do anything.


4.8. 小插曲：编码风格
=====================

现在你将要写更长，更复杂的Python代码，是时候讨论一下 *代码风格*。大多
数语言都能使用不同的风格编写（或更简洁，格式化的）；有些比其他的更具有
可读性。能让其他人轻松阅读你的代码总是一个好主意，采用一种好的编码风格
对此有很大帮助。

对于Python，**PEP 8** 已经成为大多数项目所遵循的风格指南；它促进了一种
非常易读且令人赏心悦目的编码风格。每个Python开发人员都应该在某个时候阅
读它；以下是为你提取的最重要的几个要点：

* 使用4个空格缩进，不要使用制表符。

  4个空格是一个在小缩进（允许更大的嵌套深度）和大缩进（更容易阅读）的
  一种很好的折中方案。制表符会引入混乱，最好不要使用它。

* 换行，使一行不超过79个字符。

  这有助于使用小型显示器的用户，并且可以在较大的显示器上并排放置多个代
  码文件。

* 使用空行分隔函数和类，以及函数内的较大的代码块。

* 如果可能，把注释放到单独的一行。

* 使用文档字符串。

* 在运算符前后和逗号后使用空格，但不能直接在括号内使用： "a = f(1,
  2) + g(3, 4)"。

* Name your classes and functions consistently; the convention is to
  use "CamelCase" for classes and "lower_case_with_underscores" for
  functions and methods.  Always use "self" as the name for the first
  method argument (see 初探类 for more on classes and methods).

* Don’t use fancy encodings if your code is meant to be used in
  international environments.  Plain ASCII works best in any case.

-[ 脚注 ]-

[1] 实际上，*通过对象引用调用* 会是一个更好的表述，因为如果传递的
    是可 变对象，则调用者将看到被调用者对其做出的任何更改（插入到列表
    中的元 素）。
