4.More Control Flow Tools 控制流工具

4. More Control Flow Tools 控制流工具

Besides the while statement just introduced, Python knows the usual control flow statements known from other languages, with some twists.
除了介绍的 while语句, Python从其他语言中借鉴了常用的控制流语句,并做了部分修改。

4.1. if Statements If 语句

Perhaps the most well-known statement type is the if statement. For example:
也许就著名的语句类型就是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

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 ifelifelif … sequence is a substitute for the switchor case statements found in other languages.
这里可以有0个或多个 elif, 并且 else语句也是可选的。 关键字 elifelse if 的缩写,这样可以有效的避免过多的缩进。 一个if ... elif ... elif ... 语句是其他语言中 switch 或 case 语句的替代品。

4.2. for Statements For 语句

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):
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

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']

With for w in words:, the example would attempt to create an infinite list, inserting defenestrate over and over again.
相对于 or w in words:, 这个例子将会创建一个无限的列表,一直重复插入'defenestrate'。(译者注:因为insert操作的是word列表本身,如果一直循环迭代元素的也是word本身,就会陷入死循环。用了切片来复制一个word列表来循环迭代,这个时候新插入的元素就不会影响到迭代了。)

4.3. The range() Function range() 函数

If you do need to iterate over a sequence of numbers, the built-in function range() comes in handy. It generates arithmetic progressions:
如果你需要在数字序列中迭代,内置的函数range()就可以顺手拈来。下面的例如可以产生一个算数级数:

>>> for i in range(5):
...     print(i)
...
0
1
2
3
4

The given end point is never part of the generated sequence; range(10) generates 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() 产生10个值,一个长度是10的序列中元素合法的下标。可以让这个范围起始于另外一个号码,或者指定一个不同的增长(甚至是负数增长,有时也叫做步长):

range(5, 10)
   5, 6, 7, 8, 9

range(0, 10, 3)
   0, 3, 6, 9

range(-10, -100, -30)
  -10, -40, -70

To iterate over the indices of a sequence, you can combine range() and len() as follows:
你可以组合使用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

In most such cases, however, it is convenient to use the enumerate() function, see Looping Techniques.
然而,在最多的案例中,使用enumerate() 函数是更方便的,可以查看Looping Techniques:循环的技巧.

A strange thing happens if you just print a range:
当你打印一个range时,会发生奇怪的事情:

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

In many ways the object returned by range() behaves as if it is a list, but in fact it isn’t. It is an object which returns the successive items of the desired sequence when you iterate over it, but it doesn’t really make the list, thus saving space.
在很多方法中,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:
我们所说的这个对象就是迭代器: 很适合作为那些期望获得连续的元素直到最后的函数和构造器的目标。我们可以看出for语句就是这个迭代器,list()函数就是另外一个,它从迭代器中创建列表:

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

Later we will see more functions that return iterables and take iterables as argument.
稍后我们将会看到更多函数返回迭代器并将迭代器作为参数。

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

循环中的breakcontinue语句,以及 else条款

The break statement, like in C, breaks out of the innermost enclosing for or while loop.
break语句,跟C中的一样,跳出forwhile 最里面的一层循环。

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:
循环语句中也可以有一个else分支。当循环遍历完列表后中断或循环条件为假时就会执行,但不是当循环是通过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 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

(Yes, this is the correct code. Look closely: the else clause belongs to the for loop, not the if statement.)
(是的,这就是正确的代码。看清楚了: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 elseclause runs when no break occurs. For more on the try statement and exceptions, see Handling Exceptions.
当使用一个循环的时候,else条款跟 try语句的else有更多的共同点,而不是 if中的。当没有异常发生的时候,try语句中的else条款运行,当没有break发生的时候,循环中的else条款执行。更多关于try语句和异常,请查看 Handling Exceptions:处理异常.

The continue statement, also borrowed from C, continues with the next iteration of the loop:
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 语句

The pass statement does nothing. It can be used when a statement is required syntactically but the program requires no action. For example:
pass 语句不做任何事。当仅仅是一个语句的语法要求但程序并没有任何操作要求时,可以使用它.例如:

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

This is commonly used for creating minimal classes:
这个也经常用来创建一个最小的类:

>>> 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:
另外一个用到pass的地方就是当你在写新的代码的时候,可以用它为函数或条件体占位,这样允许你在一个更加抽象的水平来继续你的思考。pass就会被默默的忽略:

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

4.6. Defining Functions 定义函数

We can create a function that writes the Fibonacci series to an arbitrary boundary:
我们可以创建一个函数来写出随意边界的斐波那契数列:

>>> 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.
关键字def介绍了一个函数的定义。它后面必须跟着函数名和括号内的形参数列表。组成函数体的语句在下一行开始,并且必须缩进。

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 Documentation Strings.) 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.
函数体的第一个语句可以选择是一个字符串常量。这个字符串常量是这个函数的文档字符串(更多关于文档字符串可以在[Documentation Strings 文档字符串]节选查看(https://docs.python.org/3/tutorial/controlflow.html#tut-docstrings))。这些是用文档字符串来自动生成线上或打印文档,或让用户通过浏览代码来进行交互的工具。写代码的时候包含文档字符串是一个很好的实践,所以请把这个作为一个习惯来看待。

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不是一个函数,而是一个过程,因为它没有返回值。事实上,即使函数没有return语句,也始终会返回一个值,即使是个没有很无聊的值。这个值被称为 None(这是一个内置的名称)。如果None是唯一被打印的值,解释器通常是抑制打印输出的(译者注:也就是省略打印None)。如果你真的想要看看你可以使用print():

>>> fib(0)   #这个按回车之后解释器没有任何输出
>>> print(fib(0))   #实际这个函数的返回值是一个None
None

It is simple to write a function that returns a list of the numbers of the Fibonacci series, instead of printing it:
很容易写一个函数来返回斐波那契数列列表的函数,来替代直接打印输出:

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

This example, as usual, demonstrates some new Python features:
这个例子,跟往常一样,演示了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.

  • return 语句从函数中返回一个值。return语句中没有任何表达式参数将会返回None。在函数的最后前运行出错也会返回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 Classes) 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.

  • result.append(a) 语句调用了列表对象 result的方法。一个方法就是一个属于一个对象的函数,命名为 obj.methodname,这个obj就是对象(这里也可以是一个表达式),methodname就是这个对象类型定义的方法名。不同的类型定义不同的方法。不同的方法可以有同样的命名且不引起歧义。(你可以用类来定义你自己的对象类型和方法,具体查看Classes) 这个例子中展示的方法append()就是列表对象定义的。它在列表的末尾添加一个新的元素。在这个例子中,它等价于 result = result + [a], 当更高效。

4.7. More on Defining Functions 更多关于定义函数

It is also possible to define functions with a variable number of arguments. There are three forms, which can be combined.
也可以定义一个参数数量可变的函数。这里有三种形式,可以组合使用:

4.7.1. Default Argument Values 默认参数值

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)

This function can be called in several ways:

  • 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 yesor no!')

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

  • 只提供必须的参数:ask_ok('Do you really want to quit?')
  • 提供一个可选的参数: ask_ok('Do you really want to quit?', 2)
  • 或者提供所有参数:ask_ok('OK to overwrite the file?', 2, 'Come on, only yesor no!')

This example also introduces the in keyword. This tests whether or not a sequence contains a certain value.
这个例子也在in
关键字中介绍,这个用来测试一个序列中是否包含一个特定的值。

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.
将会打印 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. Keyword Arguments 关键字参数

Functions can also be called using keyword arguments of the form kwarg=value. For instance, the following function:
函数也可以用kwarg=value这样形式的关键字参数来调用。例如,下面的函数:

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:
接收一个必选的参数(voltage)和三个可选的参数(state, action, and 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

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 parrotfunction), 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:
在函数调用中,关键字参数必须遵循位置参数。所有的关键字参数传递必须匹配函数接收的某个参数(例如 actorparrot函数中就是一个非法的参数),并且他们的顺序是不重要的。这个也包括非可选参数(例如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 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:
当形参是以**name的形式出现时,它接收一个字典(具体看 Mapping Types — dict Map类型--字典),包含所有的除了与其他形参相关联的关键字参数。这可以跟*name形式的形参结合起来(会在下一节讨论),它接收包含形参列表之外的位置参数的元组。(*name必须出现在**name 之前)。例如,如果我们定义一个这样的函数:

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. Arbitrary Argument Lists[] 随意参数列表

(https://docs.python.org/3/tutorial/controlflow.html#arbitrary-argument-lists "Permalink to this headline")

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 Tuples and Sequences). Before the variable number of arguments, zero or more normal arguments may occur.
最后,最不常用的选项就是调用一个任意数量参数的函数。这些参数会被包含在一个元组(请看Tuples and Sequences 元组和序列)。在可变数量的参数之前,0个或者更多正常的参数都可能出现。

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 *argsparameter are ‘keyword-only’ arguments, meaning that they can only be used as keywords rather than positional arguments.
正常情况下,那些可变参数会在形参列表的最后,因为他们承接了传给函数的剩下的输入参数。出现在*args后面的任何形参都只能是关键子参数,这也意味着他们只能够被用作关键字参数,而不是位置参数。

>>> 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. Unpacking Argument Lists[] 参数列表的拆分 (https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists "Permalink to this headline")

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:
相反的是当参数已经是一个列表或元组,却需要为要求独立位置参数的函数调用把参数拆分开。例如, 内置函数range() 期待分离的开始和末尾参数。如果他们不能分别单独获取,可以用*操作符来写函数调用,将参数从列表或元组中拆分出来。

>>> 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 Expressions[] Lambda 表达式

(https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions "Permalink to this headline")

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:
小的匿名函数可以通过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

The above example uses a lambda expression to return a function. Another use is to pass a small function as an argument:
上面的例子用一个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. Documentation Strings[] 文档字符串(https://docs.python.org/3/tutorial/controlflow.html#documentation-strings "Permalink to this headline")

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).
Python解析器不会从多行的文档字符串中去掉缩进,所以如果需要的话,处理文档的工具可以去掉多余的空行。这是使用下面的约定来完成的。文档字符串中第一行后面的第一个非空行决定了整个文档字符串的缩进个数。(我们不能使用第一行,因为它通常是邻近字符串起始的引号,所以它的缩进在字符串文字中不明显)空白相当于脱离了所有行的字符串的开始的缩进。缩进的行不应该出现,但是如果它们出现,则应该剥离它们的所有前导空格。应该测试tab键和空格键的等效性(正常一个tab等于8个空格)。

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[]

函数注解 (https://docs.python.org/3/tutorial/controlflow.html#function-annotations "Permalink to this headline")

Function annotations are completely optional metadata information about the types used by user-defined functions (see PEP 3107 and PEP 484 for more information).
函数注解是关于用户自定义函数使用的类型的完全可选元数据信息。(详细请查看 PEP 3107PEP 484

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:
注解以字典的形式保存在函数的__annotations__属性中,对函数其他部分没有影响。参数注解是在参数名后的冒号定义,紧跟着一个表达式,用来评估注解的值。返回值注解是由一个文本字符 -> 定义,后面跟随一个表达式,处于参数列表和表示def语句结束的冒号之间.下面的例如有位置参数,关键字参数和返回值注解:

>>> 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. Intermezzo: Coding Style[]

间奏曲:编码风格 (https://docs.python.org/3/tutorial/controlflow.html#intermezzo-coding-style "Permalink to this headline")

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.
现在你即将要写更长更复杂块的Python代码了,这是个谈论编码风格的好时机。大部分编程可以写成不同风格(或更简洁的说,格式化)。其中有一些相对而言更具有可读性。让其他人更容易读懂你的代码总是极好的,而且采用好的编码风格对此有极大帮助。

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:
对于Python而言,PEP8 是作为大部分项目采用的风格指导。它推动了非常具有可读性且赏心悦目的编码风格。某种程度而言,每一个Python开发者都应该读一读它。这里为你提取了最重要的几点:

  • Use 4-space indentation, and no tabs.
    使用4个空格的缩进,而不是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.
    4 个空格是在小的缩进(允许更大的嵌套深度)和大缩进之间一个好的妥协。Tabs则会导致混乱,最好将其省略。

  • Wrap lines so that they don’t exceed 79 characters.
    换行,所有它们不会超过79个字符

    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).
    在操作符周围和逗号后面使用空格, 但在括号里面不需要: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 A First Look at Classes for more on classes and methods).
    用统一的规则来命名类和函数。一般的惯例是,类名使用驼峰命名,函数和方法使用小写字母和下划线。总是使用self 作为第一个方法参数的命名。(更高关于类和方法请查看:A First Look at Classes 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.
    如果你的代码要在国际环境中使用,请不要使用花俏的编码格式。Python默认的是UTF8,即使是空白的ASCII在任何时候也是最好的。

  • 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.
    同样,只要其他不同语言的人有任何机会来阅读或保存你的代码,那么不要使用非ASCII字符作为标识符。

Footnotes 注脚

| [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). |

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容