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

可以没有或者有多个 "elif" 语句块，而 "else" 块也不是必须的。关键字
'"elif"' 是 'else if' 的简写，而且避免了过多的缩进。一组 "if" … "elif"
… "elif" 语句在其他语言里可能要写成 "switch" 或 "case" 语句。


4.2. "for" 语句
===============

Python 中的关键字 "for" 与你可能熟悉的 C 语言或者 Pascal 不同。它不像
Pascal 那样累加循环，也不像 C 语言那样让用户自定义步进和终止条件，
Python 中的 "for" 语句对序列（比如列表或字符串）进行循环（按照它们在序
列中的顺序）。例如：

   >>> # 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)
   ...
   0
   1
   2
   3
   4

给定的终止数值并不在要生成的序列里；>>``<<range(10)``会生成10个值，并
且是以合法的索引生成一个长度为10的序列。range也可以以另一个数字开头，
或者以指定的幅度增加（甚至是负数；有时这也被叫做 '步进'）

   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()" 函数比较方便，请参见 循环
的技巧.

如果你只打印 range，会出现奇怪的结果:

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

有时候:func:>>`<<range`返回的对象表现得像个列表，但它并不是列表。当你
迭代这个对象时，它会像序列一样返回正确的元素，但它并不是真的生成了个列
表，这种操作可以节省空间。

We say such an object is *iterable*, that is, suitable as a target for
functions and constructs that expect something from which they can
obtain successive items until the supply is exhausted. We have seen
that the "for" statement is such an *iterator*. The function "list()"
is another; it creates lists from iterables:

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

后面，我们会看到更多返回可迭代对象的函数，和以可迭代对象作为参数的函数
。


4.4. "break" 和 "continue" 语句, 和循环的 "else" 子句
=====================================================

"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 Handling Exceptions.

:keyword:>>`<<语句，也是从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
   ...

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, 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

The keyword "def" introduces a function *definition*.  It must be
followed by the function name and the parenthesized list of formal
parameters. The statements that form the body of the function start at
the next line, and must be indented.

The first statement of the function body can optionally be a string
literal; this string literal is the function's documentation string,
or *docstring*. (More about docstrings can be found in the section 文
档字符串.) There are tools which use docstrings to automatically
produce online or printed documentation, or to let the user
interactively browse through code; it's good practice to include
docstrings in code that you write, so make a habit of it.

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.

The actual parameters (arguments) to a function call are introduced in
the local symbol table of the called function when it is called; thus,
arguments are passed using *call by value* (where the *value* is
always an object *reference*, not the value of the object). [1] When a
function calls another function, a new local symbol table is created
for that call.

A function definition introduces the function name in the current
symbol table. The value of the function name has a type that is
recognized by the interpreter as a user-defined function.  This value
can be assigned to another name which can then also be used as a
function.  This serves as a general renaming mechanism:

   >>> 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".

* The statement "result.append(a)" calls a *method* of the list
  object "result".  A method is a function that 'belongs' to an object
  and is named "obj.methodname", where "obj" is some object (this may
  be an expression), and "methodname" is the name of a method that is
  defined by the object's type. Different types define different
  methods.  Methods of different types may have the same name without
  causing ambiguity.  (It is possible to define your own object types
  and methods, using *classes*, see 类) The method "append()" shown in
  the example is defined for list objects; it adds a new element at
  the end of the list.  In this example it is equivalent to "result =
  result + [a]", but more efficient.


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

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


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

The most useful form is to specify a default value for one or more
arguments. This creates a function that can be called with fewer
arguments than it is defined to allow.  For example:

   def ask_ok(prompt, retries=4, reminder='Please try again!'):
       while True:
           ok = 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 ValueError('invalid user response')
           print(reminder)

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

* giving only the mandatory argument: "ask_ok('Do you really want to
  quit?')"

* giving one of the optional arguments: "ask_ok('OK to overwrite the
  file?', 2)"

* or even giving all arguments: "ask_ok('OK to overwrite the file?',
  2, 'Come on, only yes or no!')"

This example also introduces the "in" keyword. This tests whether or
not a sequence contains a certain value.

The default values are evaluated at the point of function definition
in the *defining* scope, so that

   i = 5

   def f(arg=i):
       print(arg)

   i = 6
   f()

will print "5".

**Important warning:**  The default value is evaluated only once. This
makes a difference when the default is a mutable object such as a
list, dictionary, or instances of most classes.  For example, the
following function accumulates the arguments passed to it on
subsequent calls:

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

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

This will print

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

If you don't want the default to be shared between subsequent calls,
you can write the function like this instead:

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


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

Functions can also be called using *keyword arguments* of the form
"kwarg=value".  For instance, the following function:

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

accepts one required argument ("voltage") and three optional arguments
("state", "action", and "type").  This function can be called in any
of the following ways:

   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

but all the following calls would be invalid:

   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

In a function call, keyword arguments must follow positional
arguments. All the keyword arguments passed must match one of the
arguments accepted by the function (e.g. "actor" is not a valid
argument for the "parrot" function), and their order is not important.
This also includes non-optional arguments (e.g. "parrot(voltage=1000)"
is valid too). No argument may receive a value more than once. Here's
an example that fails due to this restriction:

   >>> 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 Mapping Types --- 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)
       for kw in keywords:
           print(kw, ":", keywords[kw])

It could be called like this:

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

and of course it would print:

   -- 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.
   ----------------------------------------
   shopkeeper : Michael Palin
   client : John Cleese
   sketch : Cheese Shop Sketch

Note that the order in which the keyword arguments are printed is
guaranteed to match the order in which they were provided in the
function call.


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

Finally, the least frequently used option is to specify that a
function can be called with an arbitrary number of arguments.  These
arguments will be wrapped up in a tuple (see 元组和序列).  Before the
variable number of arguments, zero or more normal arguments may occur.

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

Normally, these "variadic" arguments will be last in the list of
formal parameters, because they scoop up all remaining input arguments
that are passed to the function. Any formal parameters which occur
after the "*args" parameter are 'keyword-only' arguments, meaning that
they can only be used as keywords rather than positional arguments.

   >>> def concat(*args, sep="/"):
   ...     return sep.join(args)
   ...
   >>> concat("earth", "mars", "venus")
   'earth/mars/venus'
   >>> concat("earth", "mars", "venus", sep=".")
   'earth.mars.venus'


4.7.4. 参数列表的展开
---------------------

The reverse situation occurs when the arguments are already in a list
or tuple but need to be unpacked for a function call requiring
separate positional arguments.  For instance, the built-in "range()"
function expects separate *start* and *stop* arguments.  If they are
not available separately, write the function call with the
"*"-operator to unpack the arguments out of a list or tuple:

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

In the same fashion, dictionaries can deliver keyword arguments with
the "**"-operator:

   >>> def parrot(voltage, state='a stiff', action='voom'):
   ...     print("-- This parrot wouldn't", action, end=' ')
   ...     print("if you put", voltage, "volts through it.", end=' ')
   ...     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 表达式
--------------------

Small anonymous functions can be created with the "lambda" keyword.
This function returns the sum of its two arguments: "lambda a, b:
a+b". Lambda functions can be used wherever function objects are
required.  They are syntactically restricted to a single expression.
Semantically, they are just syntactic sugar for a normal function
definition.  Like nested function definitions, lambda functions can
reference variables from the containing scope:

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

The above example uses a lambda expression to return a function.
Another use is to pass a small function as an argument:

   >>> 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. 文档字符串
-----------------

Here are some conventions about the content and formatting of
documentation strings.

The first line should always be a short, concise summary of the
object's purpose.  For brevity, it should not explicitly state the
object's name or type, since these are available by other means
(except if the name happens to be a verb describing a function's
operation).  This line should begin with a capital letter and end with
a period.

If there are more lines in the documentation string, the second line
should be blank, visually separating the summary from the rest of the
description.  The following lines should be one or more paragraphs
describing the object's calling conventions, its side effects, etc.

The Python parser does not strip indentation from multi-line string
literals in Python, so tools that process documentation have to strip
indentation if desired.  This is done using the following convention.
The first non-blank line *after* the first line of the string
determines the amount of indentation for the entire documentation
string.  (We can't use the first line since it is generally adjacent
to the string's opening quotes so its indentation is not apparent in
the string literal.)  Whitespace "equivalent" to this indentation is
then stripped from the start of all lines of the string.  Lines that
are indented less should not occur, but if they occur all their
leading whitespace should be stripped.  Equivalence of whitespace
should be tested after expansion of tabs (to 8 spaces, normally).

Here is an example of a multi-line docstring:

   >>> 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.7.7. 函数的注解
-----------------

Function annotations are completely optional metadata information
about the types used by user-defined functions (see **PEP 3107** and
**PEP 484** for more information).

Annotations are stored in the "__annotations__" attribute of the
function as a dictionary and have no effect on any other part of the
function.  Parameter annotations are defined by a colon after the
parameter name, followed by an expression evaluating to the value of
the annotation.  Return annotations are defined by a literal "->",
followed by an expression, between the parameter list and the colon
denoting the end of the "def" statement.  The following example has a
positional argument, a keyword argument, and the return value
annotated:

   >>> def f(ham: str, eggs: str = 'eggs') -> str:
   ...     print("Annotations:", f.__annotations__)
   ...     print("Arguments:", ham, eggs)
   ...     return ham + ' and ' + eggs
   ...
   >>> f('spam')
   Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
   Arguments: spam eggs
   'spam and eggs'


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

Now that you are about to write longer, more complex pieces of Python,
it is a good time to talk about *coding style*.  Most languages can be
written (or more concise, *formatted*) in different styles; some are
more readable than others. Making it easy for others to read your code
is always a good idea, and adopting a nice coding style helps
tremendously for that.

For Python, **PEP 8** has emerged as the style guide that most
projects adhere to; it promotes a very readable and eye-pleasing
coding style.  Every Python developer should read it at some point;
here are the most important points extracted for you:

* Use 4-space indentation, and no tabs.

  4 spaces are a good compromise between small indentation (allows
  greater nesting depth) and large indentation (easier to read).  Tabs
  introduce confusion, and are best left out.

* Wrap lines so that they don't exceed 79 characters.

  This helps users with small displays and makes it possible to have
  several code files side-by-side on larger displays.

* Use blank lines to separate functions and classes, and larger
  blocks of code inside functions.

* When possible, put comments on a line of their own.

* Use docstrings.

* Use spaces around operators and after commas, but not directly
  inside bracketing constructs: "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.  Python's default, UTF-8, or even plain
  ASCII work best in any case.

* Likewise, don't use non-ASCII characters in identifiers if there
  is only the slightest chance people speaking a different language
  will read or maintain the code.

-[ 脚注 ]-

[1] Actually, *call by object reference* would be a better
    description, since if a mutable object is passed, the caller will
    see any changes the callee makes to it (items inserted into a
    list).
