4. More Control Flow Tools

4. 其他流程控制工具

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



4.1. "if" Statements

4.1. "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 "if" ... "elif" ... "elif" ... sequence is a substitute for the "switch" or "case" statements found in other languages.
可以有零个或多个 "elif" 部分,以及一个可选的 "else" 部分。 关键字'"elif"' 是 'else if' 的缩写,适合用于避免过多的缩进。 一个 "if" ..."elif" ... "elif" ... 序列可以看作是其他语言中的 "switch" 或 "case" 语句的替代。



4.2. "for" Statements

4.2. "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 中可能用到的有所不同。 Python中的 "for" 语句并不总是对算术递增的数值进行迭代(如同 Pascal),或是给予用户定义迭代步骤和暂停条件的能力(如同 C),而是对任意序列进行迭代(例如列表或字符串),条目的迭代顺序与它们在序列中出现的顺序一致。 例如(此处英文为双关语):

   >>> # Measure some strings: 
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
... print(w, len(w))
...
cat 3
window 6
defenestrate 12
Code that modifies a collection while iterating over that same collection can be tricky to get right. Instead, it is usually more straight-forward to loop over a copy of the collection or to create a new collection:
Code that modifies a collection while iterating over that samecollection can be tricky to get right. Instead, it is usually morestraight-forward to loop over a copy of the collection or to create anew collection:

   # Strategy:  Iterate over a copy 
for user, status in users.copy().items():
if status == 'inactive':
del users[user]
# Strategy: Create a new collection
active_users = {}
for user, status in users.items():
if status == 'active':
active_users[user] = status

4.3. The "range()" Function

4.3. "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个值,并且是以合法的索引生成一个长度为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
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()" 函数比较方便,请参见 循环的技巧 。

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 a construct, while an example of function that takes an iterable is "sum()":
We say such an object is iterable, that is, suitable as a target forfunctions and constructs that expect something from which they canobtain successive items until the supply is exhausted. We have seenthat the "for" statement is such a construct, while an example offunction that takes an iterable is "sum()":

   >>> sum(range(4))  # 0 + 1 + 2 + 3 
6
Later we will see more functions that return iterables and take iterables as arguments. Lastly, maybe you are curious about how to get a list from a range. Here is the solution:
Later we will see more functions that return iterables and takeiterables as arguments. Lastly, maybe you are curious about how toget a list from a range. Here is the solution:

   >>> list(range(4)) 
[0, 1, 2, 3]
In chapter Data Structures, we will discuss in more detail about "list()".
In chapter 数据结构, we will discuss in more detail about "list()".



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

4.4. "break" 和 "continue" 语句,以及循环中的 "else" 子句

The "break" statement, like in C, breaks out of the innermost enclosing "for" or "while" loop.
"break" 语句,和 C 中的类似,用于跳出最近的 "for" 或 "while" 循环.

Loop statements may have an "else" clause; it is executed when the loop terminates through exhaustion of the iterable (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:
Loop statements may have an "else" clause; it is executed when theloop terminates through exhaustion of the iterable (with "for") orwhen the condition becomes false (with "while"), but not when the loopis terminated by a "break" statement. This is exemplified by thefollowing 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
(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 with 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.
When used with a loop, the "else" clause has more in common with the"else" clause of a "try" statement than it does with that of "if"statements: a "try" statement's "else" clause runs when no exceptionoccurs, and a loop's "else" clause runs when no "break" occurs. Formore on the "try" statement and exceptions, see 处理异常.

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

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

4.6. 定义函数

We can create a function that writes the Fibonacci series to an arbitrary boundary:
我们可以创建一个输出任意范围内 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.
关键字 "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.
函数体的第一个语句可以(可选的)是字符串文字;这个字符串文字是函数的文档字符串或 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 and variables of enclosing functions cannot be directly assigned a value within a function (unless, for global variables, named in a "global" statement, or, for variables of enclosing functions, named in a "nonlocal" statement), although they may be referenced.
函数的 执行 会引入一个用于函数局部变量的新符号表。 更确切地说,函数中所有的变量赋值都将存储在局部符号表中;而变量引用会首先在局部符号表中查找,然后是外层函数的局部符号表,最后是内置名称表。 因此,全局变量和外层函数的变量不能在函数内部直接赋值(除非是在 "global" 语句中定义的全局变量,或者是在 "nonlocal" 语句中定义的外层函数的变量),尽管它们可以被引用。

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.
在函数被调用时,实际参数(实参)会被引入被调用函数的本地符号表中;因此,实参是通过 按值调用 传递的(其中 值 始终是对象 引用 而不是对象的值)。[1] 当一个函数调用另外一个函数时,将会为该调用创建一个新的本地符号表。

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 

>>> 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" ,如果你真想看到它,你可以使用 "print()"

   >>> fib(0) 
>>> print(fib(0))
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" 是由对象类型中定义的方法的名 称。不同的类型可以定义不同的方法。不同类型的方法可以有相同的名称而不 会引起歧义。(可以使用 *类* 定义自己的对象类型和方法,请参阅 类 )示 例中的方法 "append()" 是为列表对象定义的;它会在列表的最后添加一个新 的元素。在这个示例中它相当于 "result = result + [a]" ,但更高效。



4.7. More on Defining Functions

4.7. 函数定义的更多形式

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

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)
This function can be called in several ways:
这个函数可以通过几种方式调用:

• giving only the mandatory argument: "ask_ok('Do you really want to quit?')"
• 只给出必需的参数:"ask_ok('Do you really want to quit?')"

• giving one of the optional arguments: "ask_ok('OK to overwrite the file?', 2)"
• 给出一个可选的参数:"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!')"
• 或者给出所有的参数:"ask_ok('OK to overwrite the file?', 2, 'Comeon, only yes or 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

4.7.2. 关键字参数

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

   >>> def function(a): 
... pass
...
>>> function(0, a=0)
Traceback (most recent call last):
File "", line 1, in
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" 的正式形参时,它会接收一个字典 (参见 映射类型 --- dict),其中包含除了与正式形参相对应的关键字参数以外的所有关键字参数。 这可以与一个形式为 "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. Special parameters

4.7.3. Special parameters

By default, arguments may be passed to a Python function either by position or explicitly by keyword. For readability and performance, it makes sense to restrict the way arguments can be passed so that a developer need only look at the function definition to determine if items are passed by position, by position or keyword, or by keyword.
By default, arguments may be passed to a Python function either byposition or explicitly by keyword. For readability and performance, itmakes sense to restrict the way arguments can be passed so that adeveloper need only look at the function definition to determine ifitems are passed by position, by position or keyword, or by keyword.

A function definition may look like:
A function definition may look like:

   def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2): 
----------- ---------- ----------
| | |
| Positional or keyword |
| - Keyword only
-- Positional only
where "/" and "*" are optional. If used, these symbols indicate the kind of parameter by how the arguments may be passed to the function: positional-only, positional-or-keyword, and keyword-only. Keyword parameters are also referred to as named parameters.
where "/" and "*" are optional. If used, these symbols indicate thekind of parameter by how the arguments may be passed to the function:positional-only, positional-or-keyword, and keyword-only. Keywordparameters are also referred to as named parameters.



4.7.3.1. Positional-or-Keyword Arguments

4.7.3.1. Positional-or-Keyword Arguments

If "/" and "*" are not present in the function definition, arguments may be passed to a function by position or by keyword.
If "/" and "*" are not present in the function definition, argumentsmay be passed to a function by position or by keyword.



4.7.3.2. Positional-Only Parameters

4.7.3.2. Positional-Only Parameters

Looking at this in a bit more detail, it is possible to mark certain parameters as positional-only. If positional-only, the parameters' order matters, and the parameters cannot be passed by keyword. Positional-only parameters are placed before a "/" (forward-slash). The "/" is used to logically separate the positional-only parameters from the rest of the parameters. If there is no "/" in the function definition, there are no positional-only parameters.
Looking at this in a bit more detail, it is possible to mark certainparameters as positional-only. If positional-only, the parameters'order matters, and the parameters cannot be passed by keyword.Positional-only parameters are placed before a "/" (forward-slash).The "/" is used to logically separate the positional-only parametersfrom the rest of the parameters. If there is no "/" in the functiondefinition, there are no positional-only parameters.

Parameters following the "/" may be positional-or-keyword or keyword-only.
Parameters following the "/" may be positional-or-keyword orkeyword-only.



4.7.3.3. Keyword-Only Arguments

4.7.3.3. Keyword-Only Arguments

To mark parameters as keyword-only, indicating the parameters must be passed by keyword argument, place an "*" in the arguments list just before the first keyword-only parameter.
To mark parameters as keyword-only, indicating the parameters mustbe passed by keyword argument, place an "*" in the arguments list justbefore the first keyword-only parameter.



4.7.3.4. Function Examples

4.7.3.4. Function Examples

Consider the following example function definitions paying close attention to the markers "/" and "*":
Consider the following example function definitions paying closeattention to the markers "/" and "*":

   >>> def standard_arg(arg): 
... print(arg)
...
>>> def pos_only_arg(arg, /):
... print(arg)
...
>>> def kwd_only_arg(*, arg):
... print(arg)
...
>>> def combined_example(pos_only, /, standard, *, kwd_only):
... print(pos_only, standard, kwd_only)
The first function definition, "standard_arg", the most familiar form, places no restrictions on the calling convention and arguments may be passed by position or keyword:
The first function definition, "standard_arg", the most familiar form,places no restrictions on the calling convention and arguments may bepassed by position or keyword:

   >>> standard_arg(2) 
2
>>> standard_arg(arg=2)
2
The second function "pos_only_arg" is restricted to only use positional parameters as there is a "/" in the function definition:
The second function "pos_only_arg" is restricted to only usepositional parameters as there is a "/" in the function definition:

   >>> pos_only_arg(1) 
1
>>> pos_only_arg(arg=1)
Traceback (most recent call last):
File "", line 1, in
TypeError: pos_only_arg() got an unexpected keyword argument 'arg'
The third function "kwd_only_args" only allows keyword arguments as indicated by a "*" in the function definition:
The third function "kwd_only_args" only allows keyword arguments asindicated by a "*" in the function definition:

   >>> kwd_only_arg(3) 
Traceback (most recent call last):
File "", line 1, in
TypeError: kwd_only_arg() takes 0 positional arguments but 1 was given
>>> kwd_only_arg(arg=3)
3
And the last uses all three calling conventions in the same function definition:
And the last uses all three calling conventions in the same functiondefinition:

   >>> combined_example(1, 2, 3) 
Traceback (most recent call last):
File "", line 1, in
TypeError: combined_example() takes 2 positional arguments but 3 were given
>>> combined_example(1, 2, kwd_only=3)
1 2 3
>>> combined_example(1, standard=2, kwd_only=3)
1 2 3
>>> combined_example(pos_only=1, standard=2, kwd_only=3)
Traceback (most recent call last):
File "", line 1, in
TypeError: combined_example() got an unexpected keyword argument 'pos_only'
Finally, consider this function definition which has a potential collision between the positional argument "name" and "**kwds" which has "name" as a key:
Finally, consider this function definition which has a potentialcollision between the positional argument "name" and "**kwds" whichhas "name" as a key:

   def foo(name, **kwds): 
return 'name' in kwds
There is no possible call that will make it return "True" as the keyword "'name'" will always to bind to the first parameter. For example:
There is no possible call that will make it return "True" as thekeyword "'name'" will always to bind to the first parameter. Forexample:

   >>> foo(1, **{'name': 2}) 
Traceback (most recent call last):
File "", line 1, in
TypeError: foo() got multiple values for argument 'name'
>>>
But using "/" (positional only arguments), it is possible since it allows "name" as a positional argument and "'name'" as a key in the keyword arguments:
But using "/" (positional only arguments), it is possible since itallows "name" as a positional argument and "'name'" as a key in thekeyword arguments:

   def foo(name, /, **kwds): 
return 'name' in kwds
>>> foo(1, **{'name': 2})
True
In other words, the names of positional-only parameters can be used in "**kwds" without ambiguity.
In other words, the names of positional-only parameters can be used in"**kwds" without ambiguity.



4.7.3.5. Recap

4.7.3.5. Recap

The use case will determine which parameters to use in the function definition:
The use case will determine which parameters to use in the functiondefinition:

   def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2): 
As guidance:
As guidance:

• Use positional-only if you want the name of the parameters to not be available to the user. This is useful when parameter names have no real meaning, if you want to enforce the order of the arguments when the function is called or if you need to take some positional parameters and arbitrary keywords.
• Use positional-only if you want the name of the parameters to notbe available to the user. This is useful when parameter names haveno real meaning, if you want to enforce the order of the argumentswhen the function is called or if you need to take some positionalparameters and arbitrary keywords.

• Use keyword-only when names have meaning and the function definition is more understandable by being explicit with names or you want to prevent users relying on the position of the argument being passed.
• Use keyword-only when names have meaning and the functiondefinition is more understandable by being explicit with names oryou want to prevent users relying on the position of the argumentbeing passed.

• For an API, use positional-only to prevent breaking API changes if the parameter's name is modified in the future.
• For an API, use positional-only to prevent breaking API changes ifthe parameter's name is modified in the future.



4.7.4. Arbitrary Argument Lists

4.7.4. 任意的参数列表

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.
最后,最不常用的选项是可以使用任意数量的参数调用函数。这些参数会被包含在一个元组里(参见 元组和序列 )。在可变数量的参数之前,可能会出现零个或多个普通参数。:

   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.
一般来说,这些 "可变参数" 将在形式参数列表的末尾,因为它们收集传递给函数的所有剩余输入参数。出现在 "*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.5. Unpacking Argument Lists

4.7.5. 解包参数列表

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()" 函数需要单独的 startstop 参数。如果它们不能单独使用,可以使用 "*"-操作符 来编写函数调用以便从列表或元组中解包参数:

   >>> 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.6. Lambda Expressions

4.7.6. 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:
可以用 "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.7. Documentation Strings

4.7.7. 文档字符串

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

4.7.8. 函数标注

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 3107* 和 PEP 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': , 'return': , 'eggs': }
Arguments: spam eggs
'spam and eggs'

4.8. Intermezzo: Coding Style

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.
现在你将要写更长,更复杂的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,PEP 8* 已经成为大多数项目所遵循的风格指南;它促进了一种非常易读且令人赏心悦目的编码风格。每个Python开发人员都应该在某个时候阅读它;以下是为你提取的最重要的几个要点:

• Use 4-space indentation, and no tabs.
• 使用4个空格缩进,不要使用制表符。

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个空格是一个在小缩进(允许更大的嵌套深度)和大缩进(更容易阅读)的一种很好的折中方案。制表符会引入混乱,最好不要使用它。

• 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 "UpperCamelCase" for classes and "lowercase_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).
• 以一致的规则为你的类和函数命名;按照惯例应使用 "UpperCamelCase" 来命 名类,而以 "lowercase_with_underscores" 来命名函数和方法。 始终应使 用 "self" 来命名第一个方法参数 (有关类和方法的更多信息请参阅 初探类) 。

• 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 默认的UTF-8 或者纯 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).
[1] 实际上,通过对象引用调用 会是一个更好的表述,因为如果传递的是可 变对象,则调用者将看到被调用者对其做出的任何更改(插入到列表中的元 素)。

results matching ""

    No results matching ""