“Python/docs/3.9/tutorial/controlflow”的版本间差异

来自菜鸟教程
Python/docs/3.9/tutorial/controlflow
跳转至:导航、​搜索
(autoload)
 
(Page commit)
 
第1行: 第1行:
 +
{{DISPLAYTITLE:4. 更多控制流工具 — Python 文档}}
 
<div id="more-control-flow-tools" class="section">
 
<div id="more-control-flow-tools" class="section">
  
 
<span id="tut-morecontrol"></span>
 
<span id="tut-morecontrol"></span>
= <span class="section-number">4. </span>More Control Flow Tools =
+
= 4. 更多控制流工具 =
  
Besides the [[../../reference/compound_stmts#while|<code>while</code>]] statement just introduced, Python uses the usual
+
除了刚刚介绍的 [[../../reference/compound_stmts#while|while]] 语句外,Python 还使用了其他语言中已知的常用流控制语句,但有一些曲折。
flow control statements known from other languages, with some twists.
 
  
 
<div id="if-statements" class="section">
 
<div id="if-statements" class="section">
  
 
<span id="tut-if"></span>
 
<span id="tut-if"></span>
== <span class="section-number">4.1. </span><code>if</code> Statements ==
+
== 4.1. if声明 ==
  
Perhaps the most well-known statement type is the [[../../reference/compound_stmts#if|<code>if</code>]] statement. For
+
也许最著名的语句类型是 [[../../reference/compound_stmts#if|if]] 语句。 例如:
example:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第19行: 第18行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; x = int(input(&quot;Please enter an integer: &quot;))
+
<syntaxhighlight lang="python3">>>> x = int(input("Please enter an integer: "))
 
Please enter an integer: 42
 
Please enter an integer: 42
&gt;&gt;&gt; if x &lt; 0:
+
>>> if x < 0:
 
...    x = 0
 
...    x = 0
 
...    print('Negative changed to zero')
 
...    print('Negative changed to zero')
第31行: 第30行:
 
...    print('More')
 
...    print('More')
 
...
 
...
More</pre>
+
More</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
There can be zero or more [[../../reference/compound_stmts#elif|<code>elif</code>]] parts, and the [[../../reference/compound_stmts#else|<code>else</code>]] part is
+
可以有零个或多个 [[../../reference/compound_stmts#elif|elif]] 部分,[[../../reference/compound_stmts#else|else]] 部分是可选的。 关键字“<code>elif</code>”是“else if”的缩写,可用于避免过度缩进。 <code>if</code> ... <code>elif</code> ... <code>elif</code> ... 序列可替代其他语言中的 <code>switch</code> <code>case</code> 语句。
optional. The keyword '<code>elif</code>' is short for 'else if', and is useful
 
to avoid excessive indentation. An <code>if</code> ... <code>elif</code> ...
 
<code>elif</code> ... sequence is a substitute for the <code>switch</code> or
 
<code>case</code> statements found in other languages.
 
  
  
第47行: 第42行:
  
 
<span id="tut-for"></span>
 
<span id="tut-for"></span>
== <span class="section-number">4.2. </span><code>for</code> Statements ==
+
== 4.2. for声明 ==
  
The [[../../reference/compound_stmts#for|<code>for</code>]] statement in Python differs a bit from what you may be used
+
Python 中的 [[../../reference/compound_stmts#for|for]] 语句与您可能在 C Pascal 中使用的语句略有不同。 Python <code>for</code> 语句不是总是迭代数字的等差数列(如在 Pascal 中),也不是让用户能够定义迭代步骤和停止条件(如 C),而是迭代任何序列(列表或字符串),按照它们在序列中出现的顺序。 例如(没有双关语意):
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 <code>for</code> 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):
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第60行: 第50行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; # Measure some strings:
+
<syntaxhighlight lang="python3">>>> # Measure some strings:
 
... words = ['cat', 'window', 'defenestrate']
 
... words = ['cat', 'window', 'defenestrate']
&gt;&gt;&gt; for w in words:
+
>>> for w in words:
 
...    print(w, len(w))
 
...    print(w, len(w))
 
...
 
...
 
cat 3
 
cat 3
 
window 6
 
window 6
defenestrate 12</pre>
+
defenestrate 12</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
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:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第80行: 第68行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre># Strategy:  Iterate over a copy
+
<syntaxhighlight lang="python3"># Strategy:  Iterate over a copy
 
for user, status in users.copy().items():
 
for user, status in users.copy().items():
 
     if status == 'inactive':
 
     if status == 'inactive':
第89行: 第77行:
 
for user, status in users.items():
 
for user, status in users.items():
 
     if status == 'active':
 
     if status == 'active':
         active_users[user] = status</pre>
+
         active_users[user] = status</syntaxhighlight>
  
 
</div>
 
</div>
第99行: 第87行:
  
 
<span id="tut-range"></span>
 
<span id="tut-range"></span>
== <span class="section-number">4.3. </span>The [[../../library/stdtypes#range|<code>range()</code>]] Function ==
+
== 4.3. 这范围() 功能 ==
  
If you do need to iterate over a sequence of numbers, the built-in function
+
如果您确实需要迭代一系列数字,内置函数 [[../../library/stdtypes#range|range()]] 会派上用场。 它生成算术级数:
[[../../library/stdtypes#range|<code>range()</code>]] comes in handy. It generates arithmetic progressions:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第108行: 第95行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; for i in range(5):
+
<syntaxhighlight lang="python3">>>> for i in range(5):
 
...    print(i)
 
...    print(i)
 
...
 
...
第115行: 第102行:
 
2
 
2
 
3
 
3
4</pre>
+
4</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The given end point is never part of the generated sequence; <code>range(10)</code> generates
+
给定的终点永远不是生成序列的一部分; <code>range(10)</code> 生成 10 个值,即长度为 10 的序列的项目的合法索引。 可以让范围从另一个数字开始,或者指定不同的增量(甚至是负数;有时这称为“步长”):
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'):
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第129行: 第113行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>range(5, 10)
+
<syntaxhighlight lang="python3">>>> list(range(5, 10))
  5, 6, 7, 8, 9
+
[5, 6, 7, 8, 9]
  
range(0, 10, 3)
+
>>> list(range(0, 10, 3))
  0, 3, 6, 9
+
[0, 3, 6, 9]
  
range(-10, -100, -30)
+
>>> list(range(-10, -100, -30))
  -10, -40, -70</pre>
+
[-10, -40, -70]</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
To iterate over the indices of a sequence, you can combine [[../../library/stdtypes#range|<code>range()</code>]] and
+
要迭代序列的索引,您可以组合 [[../../library/stdtypes#range|range()]] [[../../library/functions#len|len()]] 如下:
[[../../library/functions#len|<code>len()</code>]] as follows:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第148行: 第131行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; a = ['Mary', 'had', 'a', 'little', 'lamb']
+
<syntaxhighlight lang="python3">>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
&gt;&gt;&gt; for i in range(len(a)):
+
>>> for i in range(len(a)):
 
...    print(i, a[i])
 
...    print(i, a[i])
 
...
 
...
第156行: 第139行:
 
2 a
 
2 a
 
3 little
 
3 little
4 lamb</pre>
+
4 lamb</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
In most such cases, however, it is convenient to use the [[../../library/functions#enumerate|<code>enumerate()</code>]]
+
但是,在大多数此类情况下,使用 [[../../library/functions#enumerate|enumerate()]] 函数会很方便,请参阅 [[../datastructures#tut-loopidioms|循环技术]]
function, see [[../datastructures#tut-loopidioms|<span class="std std-ref">Looping Techniques</span>]].
 
  
A strange thing happens if you just print a range:
+
如果你只是打印一个范围,会发生一件奇怪的事情:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第170行: 第152行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; print(range(10))
+
<syntaxhighlight lang="python3">>>> range(10)
range(0, 10)</pre>
+
range(0, 10)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
In many ways the object returned by [[../../library/stdtypes#range|<code>range()</code>]] behaves as if it is a list,
+
在许多方面,[[../../library/stdtypes#range|range()]] 返回的对象表现得好像它是一个列表,但实际上它不是。 它是一个对象,当您对其进行迭代时,它会返回所需序列的连续项目,但它并没有真正生成列表,从而节省了空间。
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.
 
  
We say such an object is [[../../glossary#term-iterable|<span class="xref std std-term">iterable</span>]], that is, suitable as a target for
+
我们说这样的对象是 [[../../glossary#term-iterable|iterable]],也就是说,适合作为函数和构造的目标,这些函数和构造期望从中获得连续的项目,直到供应耗尽。 我们已经看到 [[../../reference/compound_stmts#for|for]] 语句就是这样一种结构,而一个采用可迭代对象的函数的例子是 [[../../library/functions#sum|sum()]]
functions and constructs that expect something from which they can
 
obtain successive items until the supply is exhausted. We have seen that
 
the [[../../reference/compound_stmts#for|<code>for</code>]] statement is such a construct, while an example of a function
 
that takes an iterable is [[../../library/functions#sum|<code>sum()</code>]]:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第191行: 第166行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; sum(range(4))  # 0 + 1 + 2 + 3
+
<syntaxhighlight lang="python3">>>> sum(range(4))  # 0 + 1 + 2 + 3
6</pre>
+
6</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Later we will see more functions that return iterables and take iterables as
+
稍后我们将看到更多返回可迭代对象并将可迭代对象作为参数的函数。 在[[../datastructures#tut-structures|数据结构]]一章中,我们将更详细地讨论[[../../library/stdtypes#list|list()]]
arguments. Lastly, maybe you are curious about how to get a list from a range.
 
Here is the solution:
 
 
 
<div class="highlight-python3 notranslate">
 
 
 
<div class="highlight">
 
 
 
<pre>&gt;&gt;&gt; list(range(4))
 
[0, 1, 2, 3]</pre>
 
 
 
</div>
 
 
 
</div>
 
In chapter [[../datastructures#tut-structures|<span class="std std-ref">Data Structures</span>]], we will discuss in more detail about
 
[[../../library/stdtypes#list|<code>list()</code>]].
 
  
  
第219行: 第179行:
  
 
<span id="tut-break"></span>
 
<span id="tut-break"></span>
== <span class="section-number">4.4. </span><code>break</code> and <code>continue</code> Statements, and <code>else</code> Clauses on Loops ==
+
== 4.4. break和continue声明,以及else关于循环的条款 ==
  
The [[../../reference/simple_stmts#break|<code>break</code>]] statement, like in C, breaks out of the innermost enclosing
+
[[../../reference/simple_stmts#break|break]] 语句,就像在 C 中一样,从最内层的 [[../../reference/compound_stmts#for|for]] [[../../reference/compound_stmts#while|while]] 循环中跳出。
[[../../reference/compound_stmts#for|<code>for</code>]] or [[../../reference/compound_stmts#while|<code>while</code>]] loop.
 
  
Loop statements may have an <code>else</code> clause; it is executed when the loop
+
循环语句可能有一个 <code>else</code> 子句; 当循环因可迭代对象耗尽(使用 [[../../reference/compound_stmts#for|for]])或条件变为假(使用 [[../../reference/compound_stmts#while|while]])而终止时执行,但不会在循环由 [[../reference/simple_stmts.html#break|终止时执行]break]] 语句。 下面的循环就是一个例子,它搜索素数:
terminates through exhaustion of the iterable (with [[../../reference/compound_stmts#for|<code>for</code>]]) or when the
 
condition becomes false (with [[../../reference/compound_stmts#while|<code>while</code>]]), but not when the loop is
 
terminated by a [[../../reference/simple_stmts#break|<code>break</code>]] statement. This is exemplified by the
 
following loop, which searches for prime numbers:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第234行: 第189行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; for n in range(2, 10):
+
<syntaxhighlight lang="python3">>>> for n in range(2, 10):
 
...    for x in range(2, n):
 
...    for x in range(2, n):
 
...        if n % x == 0:
 
...        if n % x == 0:
第250行: 第205行:
 
7 is a prime number
 
7 is a prime number
 
8 equals 2 * 4
 
8 equals 2 * 4
9 equals 3 * 3</pre>
+
9 equals 3 * 3</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
(Yes, this is the correct code. Look closely: the <code>else</code> clause belongs to
+
(是的,这是正确的代码。 仔细观察:<code>else</code> 子句属于 [[../../reference/compound_stmts#for|for]] 循环,'''not''' [[../../reference/compound_stmts#if|if]] 语句。)
the [[../../reference/compound_stmts#for|<code>for</code>]] loop, '''not''' the [[../../reference/compound_stmts#if|<code>if</code>]] statement.)
 
  
When used with a loop, the <code>else</code> clause has more in common with the
+
当与循环一起使用时,<code>else</code> 子句与 [[../../reference/compound_stmts#try|try]] 语句的 <code>else</code> 子句的共同点多于与 [[../../reference/compound_stmts#if|if]] 语句的共同点语句:[[../../reference/compound_stmts#try|try]] 语句的 <code>else</code> 子句在没有异常发生时运行,循环的 <code>else</code> 子句在没有 <code>break</code> 发生时运行。 有关 <code>try</code> 语句和异常的更多信息,请参阅 [[../errors#tut-handling|处理异常]]
<code>else</code> clause of a [[../../reference/compound_stmts#try|<code>try</code>]] statement than it does with that of
 
[[../../reference/compound_stmts#if|<code>if</code>]] statements: a [[../../reference/compound_stmts#try|<code>try</code>]] statement's <code>else</code> clause runs
 
when no exception occurs, and a loop's <code>else</code> clause runs when no <code>break</code>
 
occurs. For more on the <code>try</code> statement and exceptions, see
 
[[../errors#tut-handling|<span class="std std-ref">Handling Exceptions</span>]].
 
  
The [[../../reference/simple_stmts#continue|<code>continue</code>]] statement, also borrowed from C, continues with the next
+
[[../../reference/simple_stmts#continue|continue]] 语句也是从 C 中借来的,继续循环的下一次迭代:
iteration of the loop:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第272行: 第220行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; for num in range(2, 10):
+
<syntaxhighlight lang="python3">>>> for num in range(2, 10):
 
...    if num % 2 == 0:
 
...    if num % 2 == 0:
...        print(&quot;Found an even number&quot;, num)
+
...        print("Found an even number", num)
 
...        continue
 
...        continue
...    print(&quot;Found an odd number&quot;, num)
+
...    print("Found an odd number", num)
 +
...
 
Found an even number 2
 
Found an even number 2
 
Found an odd number 3
 
Found an odd number 3
第284行: 第233行:
 
Found an odd number 7
 
Found an odd number 7
 
Found an even number 8
 
Found an even number 8
Found an odd number 9</pre>
+
Found an odd number 9</syntaxhighlight>
  
 
</div>
 
</div>
第294行: 第243行:
  
 
<span id="tut-pass"></span>
 
<span id="tut-pass"></span>
== <span class="section-number">4.5. </span><code>pass</code> Statements ==
+
== 4.5. pass声明 ==
  
The [[../../reference/simple_stmts#pass|<code>pass</code>]] statement does nothing. It can be used when a statement is
+
[[../../reference/simple_stmts#pass|pass]] 语句什么也不做。 它可以在语法上需要语句但程序不需要操作时使用。 例如:
required syntactically but the program requires no action. For example:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第303行: 第251行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; while True:
+
<syntaxhighlight lang="python3">>>> while True:
 
...    pass  # Busy-wait for keyboard interrupt (Ctrl+C)
 
...    pass  # Busy-wait for keyboard interrupt (Ctrl+C)
...</pre>
+
...</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
This is commonly used for creating minimal classes:
+
这通常用于创建最小类:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第316行: 第264行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; class MyEmptyClass:
+
<syntaxhighlight lang="python3">>>> class MyEmptyClass:
 
...    pass
 
...    pass
...</pre>
+
...</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Another place [[../../reference/simple_stmts#pass|<code>pass</code>]] can be used is as a place-holder for a function or
+
另一个可以使用 [[../../reference/simple_stmts#pass|pass]] 的地方是在您处理新代码时作为函数或条件体的占位符,让您可以在更抽象的层次上继续思考。 <code>pass</code> 被默默忽略:
conditional body when you are working on new code, allowing you to keep thinking
 
at a more abstract level. The <code>pass</code> is silently ignored:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第331行: 第277行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def initlog(*args):
+
<syntaxhighlight lang="python3">>>> def initlog(*args):
 
...    pass  # Remember to implement this!
 
...    pass  # Remember to implement this!
...</pre>
+
...</syntaxhighlight>
  
 
</div>
 
</div>
第343行: 第289行:
  
 
<span id="tut-functions"></span>
 
<span id="tut-functions"></span>
== <span class="section-number">4.6. </span>Defining Functions ==
+
== 4.6. 定义函数 ==
  
We can create a function that writes the Fibonacci series to an arbitrary
+
我们可以创建一个函数,将斐波那契数列写入任意边界:
boundary:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第352行: 第297行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def fib(n):    # write Fibonacci series up to n
+
<syntaxhighlight lang="python3">>>> def fib(n):    # write Fibonacci series up to n
...    &quot;&quot;&quot;Print a Fibonacci series up to n.&quot;&quot;&quot;
+
...    """Print a Fibonacci series up to n."""
 
...    a, b = 0, 1
 
...    a, b = 0, 1
...    while a &lt; n:
+
...    while a < n:
 
...        print(a, end=' ')
 
...        print(a, end=' ')
 
...        a, b = b, a+b
 
...        a, b = b, a+b
 
...    print()
 
...    print()
 
...
 
...
&gt;&gt;&gt; # Now call the function we just defined:
+
>>> # Now call the function we just defined:
 
... fib(2000)
 
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597</pre>
+
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The keyword [[../../reference/compound_stmts#def|<code>def</code>]] introduces a function ''definition''. It must be
+
关键字 [[../../reference/compound_stmts#def|def]] 引入了函数 ''definition''。 它后面必须是函数名和带括号的形式参数列表。 构成函数体的语句从下一行开始,并且必须缩进。
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;
+
函数体的第一条语句可以选择是字符串文字; 此字符串文字是函数的文档字符串,或 ''docstring''。 (有关文档字符串的更多信息可以在 [[#tut-docstrings|文档字符串]] 部分找到。)有一些工具可以使用文档字符串自动生成在线或打印文档,或者让用户以交互方式浏览代码; 在您编写的代码中包含文档字符串是一种很好的做法,因此请养成习惯。
this string literal is the function's documentation string, or ''docstring''.
 
(More about docstrings can be found in the section [[#tut-docstrings|<span class="std std-ref">Documentation Strings</span>]].)
 
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
+
函数的 ''execution'' 引入了一个用于函数局部变量的新符号表。 更准确地说,函数中的所有变量赋值都将值存储在本地符号表中; 而变量引用首先查看局部符号表,然后是封闭函数的局部符号表,然后是全局符号表,最后是内置名称表。 因此,全局变量和封闭函数的变量不能在函数内直接赋值(除非对于全局变量,在 [[../../reference/simple_stmts#global|global]] 语句中命名,或者对于封闭函数的变量,在 [[../reference/simple_stmts.html#nonlocal|语句中命名) ]nonlocal]] 语句),尽管它们可能会被引用。
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 [[../../reference/simple_stmts#global|<code>global</code>]] statement, or, for variables of enclosing
 
functions, named in a [[../../reference/simple_stmts#nonlocal|<code>nonlocal</code>]] statement), although they may be
 
referenced.
 
  
The actual parameters (arguments) to a function call are introduced in the local
+
函数调用的实际参数(arguments)在被调用函数的局部符号表中被引入; 因此,参数是使用 ''按值'' 调用传递的(其中 '''' 始终是对象 ''引用'' ,而不是对象的值)。 [[#id2|1]] 当一个函数调用另一个函数或递归调用自身时,会为该调用创建一个新的本地符号表。
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). [[#id2|1]] When a function calls another function, a new
 
local symbol table is created for that call.
 
  
A function definition associates the function name with the function object in
+
函数定义将函数名称与当前符号表中的函数对象相关联。 解释器将该名称指向的对象识别为用户定义的函数。 其他名称也可以指向相同的函数对象,也可以用于访问该函数:
the current symbol table. The interpreter recognizes the object pointed to by
 
that name as a user-defined function. Other names can also point to that same
 
function object and can also be used to access the function:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第405行: 第326行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; fib
+
<syntaxhighlight lang="python3">>>> fib
&lt;function fib at 10042ed0&gt;
+
<function fib at 10042ed0>
&gt;&gt;&gt; f = fib
+
>>> f = fib
&gt;&gt;&gt; f(100)
+
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89</pre>
+
0 1 1 2 3 5 8 13 21 34 55 89</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Coming from other languages, you might object that <code>fib</code> is not a function but
+
来自其他语言,您可能反对 <code>fib</code> 不是函数而是过程,因为它不返回值。 事实上,即使没有 [[../../reference/simple_stmts#return|return]] 语句的函数也会返回一个值,尽管它相当无聊。 该值称为 <code>None</code>(它是一个内置名称)。 如果写入值 <code>None</code> 是唯一写入的值,则它通常会被解释器抑制。 如果你真的想使用 [[../../library/functions#print|print()]],你可以看到它:
a procedure since it doesn't return a value. In fact, even functions without a
 
[[../../reference/simple_stmts#return|<code>return</code>]] statement do return a value, albeit a rather boring one. This
 
value is called <code>None</code> (it's a built-in name). Writing the value <code>None</code> is
 
normally suppressed by the interpreter if it would be the only value written.
 
You can see it if you really want to using [[../../library/functions#print|<code>print()</code>]]:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第425行: 第341行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; fib(0)
+
<syntaxhighlight lang="python3">>>> fib(0)
&gt;&gt;&gt; print(fib(0))
+
>>> print(fib(0))
None</pre>
+
None</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
It is simple to write a function that returns a list of the numbers of the
+
编写一个返回斐波那契数列数字列表的函数很简单,而不是打印它:
Fibonacci series, instead of printing it:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第439行: 第354行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def fib2(n):  # return Fibonacci series up to n
+
<syntaxhighlight lang="python3">>>> def fib2(n):  # return Fibonacci series up to n
...    &quot;&quot;&quot;Return a list containing the Fibonacci series up to n.&quot;&quot;&quot;
+
...    """Return a list containing the Fibonacci series up to n."""
 
...    result = []
 
...    result = []
 
...    a, b = 0, 1
 
...    a, b = 0, 1
...    while a &lt; n:
+
...    while a < n:
 
...        result.append(a)    # see below
 
...        result.append(a)    # see below
 
...        a, b = b, a+b
 
...        a, b = b, a+b
 
...    return result
 
...    return result
 
...
 
...
&gt;&gt;&gt; f100 = fib2(100)    # call it
+
>>> f100 = fib2(100)    # call it
&gt;&gt;&gt; f100                # write the result
+
>>> f100                # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]</pre>
+
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
This example, as usual, demonstrates some new Python features:
+
这个例子和往常一样,演示了一些新的 Python 特性:
  
* The [[../../reference/simple_stmts#return|<code>return</code>]] statement returns with a value from a function. <code>return</code> without an expression argument returns <code>None</code>. Falling off the end of a function also returns <code>None</code>.
+
* [[../../reference/simple_stmts#return|return]] 语句从函数返回一个值。 <code>return</code> 没有表达式参数返回 <code>None</code>。 从函数的末尾脱落也会返回 <code>None</code>
* The statement <code>result.append(a)</code> calls a ''method'' of the list object <code>result</code>. A method is a function that 'belongs' to an object and is named <code>obj.methodname</code>, where <code>obj</code> is some object (this may be an expression), and <code>methodname</code> 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#tut-classes|<span class="std std-ref">Classes</span>]]) The method <code>append()</code> 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 <code>result = result + [a]</code>, but more efficient.
+
* 语句 <code>result.append(a)</code> 调用列表对象 <code>result</code> 的 ''方法'' 。 方法是“属于”对象的函数,名为 <code>obj.methodname</code>,其中 <code>obj</code> 是某个对象(这可能是一个表达式),而 <code>methodname</code> 是名称由对象的类型定义的方法。 不同的类型定义不同的方法。 不同类型的方法可以具有相同的名称而不会引起歧义。 (可以定义自己的对象类型和方法,使用 ''classes'',参见 [[../classes#tut-classes|Classes]])示例中的方法 <code>append()</code> 是为列表对象定义的; 它在列表的末尾添加一个新元素。 在本例中,它等效于 <code>result = result + [a]</code>,但效率更高。
  
  
第465行: 第380行:
  
 
<span id="tut-defining"></span>
 
<span id="tut-defining"></span>
== <span class="section-number">4.7. </span>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.
 
  
 
<div id="default-argument-values" class="section">
 
<div id="default-argument-values" class="section">
  
 
<span id="tut-defaultargs"></span>
 
<span id="tut-defaultargs"></span>
=== <span class="section-number">4.7.1. </span>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:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第483行: 第395行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def ask_ok(prompt, retries=4, reminder='Please try again!'):
+
<syntaxhighlight lang="python3">def ask_ok(prompt, retries=4, reminder='Please try again!'):
 
     while True:
 
     while True:
 
         ok = input(prompt)
 
         ok = input(prompt)
第491行: 第403行:
 
             return False
 
             return False
 
         retries = retries - 1
 
         retries = retries - 1
         if retries &lt; 0:
+
         if retries < 0:
 
             raise ValueError('invalid user response')
 
             raise ValueError('invalid user response')
         print(reminder)</pre>
+
         print(reminder)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
This function can be called in several ways:
+
可以通过多种方式调用此函数:
  
* giving only the mandatory argument: <code>ask_ok('Do you really want to quit?')</code>
+
* 仅给出强制性参数:<code>ask_ok('Do you really want to quit?')</code>
* giving one of the optional arguments: <code>ask_ok('OK to overwrite the file?', 2)</code>
+
* 给出可选参数之一:<code>ask_ok('OK to overwrite the file?', 2)</code>
* or even giving all arguments: <code>ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')</code>
+
* 甚至给出所有参数:<code>ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')</code>
  
This example also introduces the [[../../reference/expressions#in|<code>in</code>]] keyword. This tests whether or
+
此示例还引入了 [[../../reference/expressions#in|in]] 关键字。 这将测试序列是否包含某个值。
not a sequence contains a certain value.
 
  
The default values are evaluated at the point of function definition in the
+
默认值在 ''defining'' 作用域中的函数定义点计算,因此
''defining'' scope, so that
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第514行: 第424行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>i = 5
+
<syntaxhighlight lang="python3">i = 5
  
 
def f(arg=i):
 
def f(arg=i):
第520行: 第430行:
  
 
i = 6
 
i = 6
f()</pre>
+
f()</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
will print <code>5</code>.
+
将打印 <code>5</code>
  
'''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:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第536行: 第443行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def f(a, L=[]):
+
<syntaxhighlight lang="python3">def f(a, L=[]):
 
     L.append(a)
 
     L.append(a)
 
     return L
 
     return L
第542行: 第449行:
 
print(f(1))
 
print(f(1))
 
print(f(2))
 
print(f(2))
print(f(3))</pre>
+
print(f(3))</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
This will print
+
这将打印
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第553行: 第460行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>[1]
+
<syntaxhighlight lang="python3">[1]
 
[1, 2]
 
[1, 2]
[1, 2, 3]</pre>
+
[1, 2, 3]</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
If you don't want the default to be shared between subsequent calls, you can
+
如果您不希望在后续调用之间共享默认值,则可以编写如下函数:
write the function like this instead:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第567行: 第473行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def f(a, L=None):
+
<syntaxhighlight lang="python3">def f(a, L=None):
 
     if L is None:
 
     if L is None:
 
         L = []
 
         L = []
 
     L.append(a)
 
     L.append(a)
     return L</pre>
+
     return L</syntaxhighlight>
  
 
</div>
 
</div>
第581行: 第487行:
  
 
<span id="tut-keywordargs"></span>
 
<span id="tut-keywordargs"></span>
=== <span class="section-number">4.7.2. </span>Keyword Arguments ===
+
=== 4.7.2. 关键字参数 ===
  
Functions can also be called using [[../../glossary#term-keyword-argument|<span class="xref std std-term">keyword arguments</span>]]
+
也可以使用 <code>kwarg=value</code> 形式的 [[../../glossary#term-keyword-argument|关键字参数]] 调用函数。 例如,以下函数:
of the form <code>kwarg=value</code>. For instance, the following function:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第590行: 第495行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
+
<syntaxhighlight lang="python3">def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
     print(&quot;-- This parrot wouldn't&quot;, action, end=' ')
+
     print("-- This parrot wouldn't", action, end=' ')
     print(&quot;if you put&quot;, voltage, &quot;volts through it.&quot;)
+
     print("if you put", voltage, "volts through it.")
     print(&quot;-- Lovely plumage, the&quot;, type)
+
     print("-- Lovely plumage, the", type)
     print(&quot;-- It's&quot;, state, &quot;!&quot;)</pre>
+
     print("-- It's", state, "!")</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
accepts one required argument (<code>voltage</code>) and three optional arguments
+
接受一个必需参数 (<code>voltage</code>) 和三个可选参数(<code>state</code><code>action</code> <code>type</code>)。 可以通过以下任何一种方式调用此函数:
(<code>state</code>, <code>action</code>, and <code>type</code>). This function can be called in any
 
of the following ways:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第607行: 第510行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>parrot(1000)                                          # 1 positional argument
+
<syntaxhighlight lang="python3">parrot(1000)                                          # 1 positional argument
 
parrot(voltage=1000)                                  # 1 keyword argument
 
parrot(voltage=1000)                                  # 1 keyword argument
 
parrot(voltage=1000000, action='VOOOOOM')            # 2 keyword arguments
 
parrot(voltage=1000000, action='VOOOOOM')            # 2 keyword arguments
 
parrot(action='VOOOOOM', voltage=1000000)            # 2 keyword arguments
 
parrot(action='VOOOOOM', voltage=1000000)            # 2 keyword arguments
 
parrot('a million', 'bereft of life', 'jump')        # 3 positional arguments
 
parrot('a million', 'bereft of life', 'jump')        # 3 positional arguments
parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword</pre>
+
parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
but all the following calls would be invalid:
+
但以下所有调用都是无效的:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第623行: 第526行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>parrot()                    # required argument missing
+
<syntaxhighlight lang="python3">parrot()                    # required argument missing
 
parrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argument
 
parrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argument
 
parrot(110, voltage=220)    # duplicate value for the same argument
 
parrot(110, voltage=220)    # duplicate value for the same argument
parrot(actor='John Cleese')  # unknown keyword argument</pre>
+
parrot(actor='John Cleese')  # unknown keyword argument</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
In a function call, keyword arguments must follow positional arguments.
+
在函数调用中,关键字参数必须跟在位置参数之后。 传递的所有关键字参数必须与函数接受的参数之一匹配(例如 <code>actor</code> 不是 <code>parrot</code> 函数的有效参数),它们的顺序并不重要。 这也包括非可选参数(例如 <code>parrot(voltage=1000)</code> 也有效)。 任何参数都不能多次接收一个值。 这是一个由于此限制而失败的示例:
All the keyword arguments passed must match one of the arguments
 
accepted by the function (e.g. <code>actor</code> is not a valid argument for the
 
<code>parrot</code> function), and their order is not important. This also includes
 
non-optional arguments (e.g. <code>parrot(voltage=1000)</code> is valid too).
 
No argument may receive a value more than once.
 
Here's an example that fails due to this restriction:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第643行: 第540行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def function(a):
+
<syntaxhighlight lang="python3">>>> def function(a):
 
...    pass
 
...    pass
 
...
 
...
&gt;&gt;&gt; function(0, a=0)
+
>>> function(0, a=0)
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
TypeError: function() got multiple values for keyword argument 'a'</pre>
+
TypeError: function() got multiple values for argument 'a'</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
When a final formal parameter of the form <code>**name</code> is present, it receives a
+
当存在 <code>**name</code> 形式的最终形参时,它会收到一个字典(参见 [[../../library/stdtypes#typesmapping|映射类型 — dict]]),其中包含除与形参对应的关键字参数之外的所有关键字参数。 这可以与形式参数 <code>*name</code>(在下一小节中描述)结合,该形式参数接收包含超出形式参数列表的位置参数的 [[../datastructures#tut-tuples|元组]] 。 (<code>*name</code> 必须出现在 <code>**name</code> 之前。)例如,如果我们定义这样的函数:
dictionary (see [[../../library/stdtypes#typesmapping|<span class="std std-ref">Mapping Types --- dict</span>]]) containing all keyword arguments except for
 
those corresponding to a formal parameter. This may be combined with a formal
 
parameter of the form <code>*name</code> (described in the next subsection) which
 
receives a [[../datastructures#tut-tuples|<span class="std std-ref">tuple</span>]] containing the positional
 
arguments beyond the formal parameter list. (<code>*name</code> must occur
 
before <code>**name</code>.) For example, if we define a function like this:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第666行: 第557行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def cheeseshop(kind, *arguments, **keywords):
+
<syntaxhighlight lang="python3">def cheeseshop(kind, *arguments, **keywords):
     print(&quot;-- Do you have any&quot;, kind, &quot;?&quot;)
+
     print("-- Do you have any", kind, "?")
     print(&quot;-- I'm sorry, we're all out of&quot;, kind)
+
     print("-- I'm sorry, we're all out of", kind)
 
     for arg in arguments:
 
     for arg in arguments:
 
         print(arg)
 
         print(arg)
     print(&quot;-&quot; * 40)
+
     print("-" * 40)
 
     for kw in keywords:
 
     for kw in keywords:
         print(kw, &quot;:&quot;, keywords[kw])</pre>
+
         print(kw, ":", keywords[kw])</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
It could be called like this:
+
可以这样调用:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第684行: 第575行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>cheeseshop(&quot;Limburger&quot;, &quot;It's very runny, sir.&quot;,
+
<syntaxhighlight lang="python3">cheeseshop("Limburger", "It's very runny, sir.",
           &quot;It's really very, VERY runny, sir.&quot;,
+
           "It's really very, VERY runny, sir.",
           shopkeeper=&quot;Michael Palin&quot;,
+
           shopkeeper="Michael Palin",
           client=&quot;John Cleese&quot;,
+
           client="John Cleese",
           sketch=&quot;Cheese Shop Sketch&quot;)</pre>
+
           sketch="Cheese Shop Sketch")</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
and of course it would print:
+
当然它会打印:
  
 
<div class="highlight-none notranslate">
 
<div class="highlight-none notranslate">
第699行: 第590行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>-- Do you have any Limburger ?
+
<pre class="none">-- Do you have any Limburger ?
 
-- I'm sorry, we're all out of Limburger
 
-- I'm sorry, we're all out of Limburger
 
It's very runny, sir.
 
It's very runny, sir.
第711行: 第602行:
  
 
</div>
 
</div>
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.
 
  
  
第718行: 第608行:
 
<div id="special-parameters" class="section">
 
<div id="special-parameters" class="section">
  
=== <span class="section-number">4.7.3. </span>Special parameters ===
+
=== 4.7.3. 特殊参数 ===
  
By default, arguments may be passed to a Python function either by position
+
默认情况下,参数可以通过位置或显式通过关键字传递给 Python 函数。 为了可读性和性能,限制参数的传递方式是有意义的,这样开发人员只需查看函数定义即可确定项目是按位置、按位置或关键字还是按关键字传递。
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.
 
  
A function definition may look like:
+
函数定义可能如下所示:
  
 
<div class="highlight-none notranslate">
 
<div class="highlight-none notranslate">
第732行: 第618行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
+
<pre class="none">def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
 
       -----------    ----------    ----------
 
       -----------    ----------    ----------
 
         |            |                  |
 
         |            |                  |
第742行: 第628行:
  
 
</div>
 
</div>
where <code>/</code> and <code>*</code> are optional. If used, these symbols indicate the kind of
+
其中 <code>/</code> <code>*</code> 是可选的。 如果使用,这些符号通过参数如何传递给函数来指示参数的类型:仅位置、位置或关键字和仅关键字。 关键字参数也称为命名参数。
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.
 
  
 
<div id="positional-or-keyword-arguments" class="section">
 
<div id="positional-or-keyword-arguments" class="section">
  
==== <span class="section-number">4.7.3.1. </span>Positional-or-Keyword Arguments ====
+
==== 4.7.3.1. 位置或关键字参数 ====
  
If <code>/</code> and <code>*</code> are not present in the function definition, arguments may
+
如果函数定义中不存在 <code>/</code> <code>*</code>,则可以通过位置或关键字将参数传递给函数。
be passed to a function by position or by keyword.
 
  
  
第758行: 第640行:
 
<div id="positional-only-parameters" class="section">
 
<div id="positional-only-parameters" class="section">
  
==== <span class="section-number">4.7.3.2. </span>Positional-Only Parameters ====
+
==== 4.7.3.2. 仅位置参数 ====
  
Looking at this in a bit more detail, it is possible to mark certain parameters
+
更详细地看一下,可以将某些参数标记为 ''positional-only''。 如果是''positional-only'',参数的顺序很重要,不能通过关键字传递参数。 仅位置参数放置在 <code>/</code>(正斜杠)之前。 <code>/</code> 用于在逻辑上将仅位置参数与其余参数分开。 如果函数定义中没有 <code>/</code>,则没有仅位置参数。
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 <code>/</code> (forward-slash). The <code>/</code> is used to logically
 
separate the positional-only parameters from the rest of the parameters.
 
If there is no <code>/</code> in the function definition, there are no positional-only
 
parameters.
 
  
Parameters following the <code>/</code> may be ''positional-or-keyword'' or ''keyword-only''.
+
<code>/</code> 后面的参数可以是 ''positional-or-keyword'' ''keyword-only''
  
  
第774行: 第650行:
 
<div id="keyword-only-arguments" class="section">
 
<div id="keyword-only-arguments" class="section">
  
==== <span class="section-number">4.7.3.3. </span>Keyword-Only Arguments ====
+
==== 4.7.3.3. 仅关键字参数 ====
  
To mark parameters as ''keyword-only'', indicating the parameters must be passed
+
要将参数标记为 ''keyword-only'',指示参数必须通过关键字参数传递,请在参数列表中第一个 ''keyword-only'' 参数之前放置一个 <code>*</code> .
by keyword argument, place an <code>*</code> in the arguments list just before the first
 
''keyword-only'' parameter.
 
  
  
第784行: 第658行:
 
<div id="function-examples" class="section">
 
<div id="function-examples" class="section">
  
==== <span class="section-number">4.7.3.4. </span>Function Examples ====
+
==== 4.7.3.4. 函数示例 ====
  
Consider the following example function definitions paying close attention to the
+
考虑以下示例函数定义,重点关注标记 <code>/</code> <code>*</code>
markers <code>/</code> and <code>*</code>:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第793行: 第666行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def standard_arg(arg):
+
<syntaxhighlight lang="python3">>>> def standard_arg(arg):
 
...    print(arg)
 
...    print(arg)
 
...
 
...
&gt;&gt;&gt; def pos_only_arg(arg, /):
+
>>> def pos_only_arg(arg, /):
 
...    print(arg)
 
...    print(arg)
 
...
 
...
&gt;&gt;&gt; def kwd_only_arg(*, arg):
+
>>> def kwd_only_arg(*, arg):
 
...    print(arg)
 
...    print(arg)
 
...
 
...
&gt;&gt;&gt; def combined_example(pos_only, /, standard, *, kwd_only):
+
>>> def combined_example(pos_only, /, standard, *, kwd_only):
...    print(pos_only, standard, kwd_only)</pre>
+
...    print(pos_only, standard, kwd_only)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The first function definition, <code>standard_arg</code>, the most familiar form,
+
第一个函数定义,<code>standard_arg</code>,最熟悉的形式,对调用约定没有限制,参数可以通过位置或关键字传递:
places no restrictions on the calling convention and arguments may be
 
passed by position or keyword:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第816行: 第687行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; standard_arg(2)
+
<syntaxhighlight lang="python3">>>> standard_arg(2)
 
2
 
2
  
&gt;&gt;&gt; standard_arg(arg=2)
+
>>> standard_arg(arg=2)
2</pre>
+
2</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The second function <code>pos_only_arg</code> is restricted to only use positional
+
第二个函数 <code>pos_only_arg</code> 仅限于使用位置参数,因为函数定义中有一个 <code>/</code>
parameters as there is a <code>/</code> in the function definition:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第832行: 第702行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; pos_only_arg(1)
+
<syntaxhighlight lang="python3">>>> pos_only_arg(1)
 
1
 
1
  
&gt;&gt;&gt; pos_only_arg(arg=1)
+
>>> pos_only_arg(arg=1)
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
TypeError: pos_only_arg() got an unexpected keyword argument 'arg'</pre>
+
TypeError: pos_only_arg() got some positional-only arguments passed as keyword arguments: 'arg'</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The third function <code>kwd_only_args</code> only allows keyword arguments as indicated
+
第三个函数 <code>kwd_only_args</code> 只允许关键字参数,如函数定义中的 <code>*</code> 所示:
by a <code>*</code> in the function definition:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第850行: 第719行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; kwd_only_arg(3)
+
<syntaxhighlight lang="python3">>>> kwd_only_arg(3)
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
TypeError: kwd_only_arg() takes 0 positional arguments but 1 was given
 
TypeError: kwd_only_arg() takes 0 positional arguments but 1 was given
  
&gt;&gt;&gt; kwd_only_arg(arg=3)
+
>>> kwd_only_arg(arg=3)
3</pre>
+
3</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
And the last uses all three calling conventions in the same function
+
最后一个在同一个函数定义中使用所有三个调用约定:
definition:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第868行: 第736行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; combined_example(1, 2, 3)
+
<syntaxhighlight lang="python3">>>> combined_example(1, 2, 3)
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
TypeError: combined_example() takes 2 positional arguments but 3 were given
 
TypeError: combined_example() takes 2 positional arguments but 3 were given
  
&gt;&gt;&gt; combined_example(1, 2, kwd_only=3)
+
>>> combined_example(1, 2, kwd_only=3)
 
1 2 3
 
1 2 3
  
&gt;&gt;&gt; combined_example(1, standard=2, kwd_only=3)
+
>>> combined_example(1, standard=2, kwd_only=3)
 
1 2 3
 
1 2 3
  
&gt;&gt;&gt; combined_example(pos_only=1, standard=2, kwd_only=3)
+
>>> combined_example(pos_only=1, standard=2, kwd_only=3)
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
TypeError: combined_example() got an unexpected keyword argument 'pos_only'</pre>
+
TypeError: combined_example() got some positional-only arguments passed as keyword arguments: 'pos_only'</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Finally, consider this function definition which has a potential collision between the positional argument <code>name</code> and <code>**kwds</code> which has <code>name</code> as a key:
+
最后,考虑这个函数定义,它在位置参数 <code>name</code> 和以 <code>name</code> 作为键的 <code>**kwds</code> 之间存在潜在冲突:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第893行: 第761行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def foo(name, **kwds):
+
<syntaxhighlight lang="python3">def foo(name, **kwds):
     return 'name' in kwds</pre>
+
     return 'name' in kwds</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
There is no possible call that will make it return <code>True</code> as the keyword <code>'name'</code>
+
没有可能的调用使其返回 <code>True</code>,因为关键字 <code>'name'</code> 将始终绑定到第一个参数。 例如:
will always bind to the first parameter. For example:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第906行: 第773行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; foo(1, **{'name': 2})
+
<syntaxhighlight lang="python3">>>> foo(1, **{'name': 2})
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
TypeError: foo() got multiple values for argument 'name'
 
TypeError: foo() got multiple values for argument 'name'
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
But using <code>/</code> (positional only arguments), it is possible since it allows <code>name</code> as a positional argument and <code>'name'</code> as a key in the keyword arguments:
+
但是使用 <code>/</code>(仅位置参数),这是可能的,因为它允许 <code>name</code> 作为位置参数和 <code>'name'</code> 作为关键字参数中的键:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第921行: 第788行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def foo(name, /, **kwds):
+
<syntaxhighlight lang="python3">def foo(name, /, **kwds):
 
     return 'name' in kwds
 
     return 'name' in kwds
&gt;&gt;&gt; foo(1, **{'name': 2})
+
>>> foo(1, **{'name': 2})
True</pre>
+
True</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
In other words, the names of positional-only parameters can be used in
+
换句话说,仅位置参数的名称可以在 <code>**kwds</code> 中使用而不会产生歧义。
<code>**kwds</code> without ambiguity.
 
  
  
第936行: 第802行:
 
<div id="recap" class="section">
 
<div id="recap" class="section">
  
==== <span class="section-number">4.7.3.5. </span>Recap ====
+
==== 4.7.3.5. 回顾 ====
  
The use case will determine which parameters to use in the function definition:
+
用例将确定在函数定义中使用哪些参数:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第944行: 第810行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):</pre>
+
<syntaxhighlight lang="python3">def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
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.
+
* 如果您希望参数的名称对用户不可用,请使用 positional-only。 当参数名称没有实际意义时,如果您想在调用函数时强制执行参数的顺序,或者您需要采用一些位置参数和任意关键字,这将非常有用。
* 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.
+
* 当名称有意义并且函数定义通过明确的名称更易于理解或您想防止用户依赖于传递的参数的位置时,使用仅关键字。
* For an API, use positional-only to prevent breaking API changes if the parameter's name is modified in the future.
+
* 对于 API,如果将来修改了参数名称,请使用 positional-only 来防止破坏 API 更改。
  
  
第962行: 第828行:
  
 
<span id="tut-arbitraryargs"></span>
 
<span id="tut-arbitraryargs"></span>
=== <span class="section-number">4.7.4. </span>Arbitrary Argument Lists ===
+
=== 4.7.4. 任意参数列表 ===
  
Finally, the least frequently used option is to specify that a function can be
+
最后,最不常用的选项是指定可以使用任意数量的参数调用函数。 这些参数将包含在一个元组中(参见 [[../datastructures#tut-tuples|元组和序列]] )。 在可变数量的参数之前,可能会出现零个或多个正常参数。
called with an arbitrary number of arguments. These arguments will be wrapped
 
up in a tuple (see [[../datastructures#tut-tuples|<span class="std std-ref">Tuples and Sequences</span>]]). Before the variable number of arguments,
 
zero or more normal arguments may occur.
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第973行: 第836行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>def write_multiple_items(file, separator, *args):
+
<syntaxhighlight lang="python3">def write_multiple_items(file, separator, *args):
     file.write(separator.join(args))</pre>
+
     file.write(separator.join(args))</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Normally, these <code>variadic</code> arguments will be last in the list of formal
+
通常,这些 <code>variadic</code> 参数将位于形式参数列表的最后,因为它们会收集传递给函数的所有剩余输入参数。 出现在 <code>*args</code> 参数之后的任何形式参数都是“仅关键字”参数,这意味着它们只能用作关键字而不是位置参数。
parameters, because they scoop up all remaining input arguments that are
 
passed to the function. Any formal parameters which occur after the <code>*args</code>
 
parameter are 'keyword-only' arguments, meaning that they can only be used as
 
keywords rather than positional arguments.
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第989行: 第848行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def concat(*args, sep=&quot;/&quot;):
+
<syntaxhighlight lang="python3">>>> def concat(*args, sep="/"):
 
...    return sep.join(args)
 
...    return sep.join(args)
 
...
 
...
&gt;&gt;&gt; concat(&quot;earth&quot;, &quot;mars&quot;, &quot;venus&quot;)
+
>>> concat("earth", "mars", "venus")
 
'earth/mars/venus'
 
'earth/mars/venus'
&gt;&gt;&gt; concat(&quot;earth&quot;, &quot;mars&quot;, &quot;venus&quot;, sep=&quot;.&quot;)
+
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'</pre>
+
'earth.mars.venus'</syntaxhighlight>
  
 
</div>
 
</div>
第1,005行: 第864行:
  
 
<span id="tut-unpacking-arguments"></span>
 
<span id="tut-unpacking-arguments"></span>
=== <span class="section-number">4.7.5. </span>Unpacking Argument Lists ===
+
=== 4.7.5. 解包参数列表 ===
  
The reverse situation occurs when the arguments are already in a list or tuple
+
当参数已经在列表或元组中但需要为需要单独位置参数的函数调用解包时,会发生相反的情况。 例如,内置的 [[../../library/stdtypes#range|range()]] 函数需要单独的 ''start'' ''stop'' 参数。 如果它们不能单独使用,请使用 <code>*</code> 运算符编写函数调用以将参数从列表或元组中解压缩:
but need to be unpacked for a function call requiring separate positional
 
arguments. For instance, the built-in [[../../library/stdtypes#range|<code>range()</code>]] function expects separate
 
''start'' and ''stop'' arguments. If they are not available separately, write the
 
function call with the <code>*</code>-operator to unpack the arguments out of a list
 
or tuple:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,018行: 第872行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; list(range(3, 6))            # normal call with separate arguments
+
<syntaxhighlight lang="python3">>>> list(range(3, 6))            # normal call with separate arguments
 
[3, 4, 5]
 
[3, 4, 5]
&gt;&gt;&gt; args = [3, 6]
+
>>> args = [3, 6]
&gt;&gt;&gt; list(range(*args))            # call with arguments unpacked from a list
+
>>> list(range(*args))            # call with arguments unpacked from a list
[3, 4, 5]</pre>
+
[3, 4, 5]</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
In the same fashion, dictionaries can deliver keyword arguments with the
+
以同样的方式,字典可以使用 <code>**</code> 运算符传递关键字参数:
<code>**</code>-operator:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,034行: 第887行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def parrot(voltage, state='a stiff', action='voom'):
+
<syntaxhighlight lang="python3">>>> def parrot(voltage, state='a stiff', action='voom'):
...    print(&quot;-- This parrot wouldn't&quot;, action, end=' ')
+
...    print("-- This parrot wouldn't", action, end=' ')
...    print(&quot;if you put&quot;, voltage, &quot;volts through it.&quot;, end=' ')
+
...    print("if you put", voltage, "volts through it.", end=' ')
...    print(&quot;E's&quot;, state, &quot;!&quot;)
+
...    print("E's", state, "!")
 
...
 
...
&gt;&gt;&gt; d = {&quot;voltage&quot;: &quot;four million&quot;, &quot;state&quot;: &quot;bleedin' demised&quot;, &quot;action&quot;: &quot;VOOM&quot;}
+
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
&gt;&gt;&gt; parrot(**d)
+
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !</pre>
+
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !</syntaxhighlight>
  
 
</div>
 
</div>
第1,051行: 第904行:
  
 
<span id="tut-lambda"></span>
 
<span id="tut-lambda"></span>
=== <span class="section-number">4.7.6. </span>Lambda Expressions ===
+
=== 4.7.6. Lambda 表达式 ===
  
Small anonymous functions can be created with the [[../../reference/expressions#lambda|<code>lambda</code>]] keyword.
+
可以使用 [[../../reference/expressions#lambda|lambda]] 关键字创建小型匿名函数。 此函数返回其两个参数的总和:<code>lambda a, b: a+b</code>Lambda 函数可用于需要函数对象的任何地方。 它们在语法上仅限于单个表达式。 从语义上讲,它们只是普通函数定义的语法糖。 与嵌套函数定义一样,lambda 函数可以从包含范围引用变量:
This function returns the sum of its two arguments: <code>lambda a, b: a+b</code>.
 
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:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,065行: 第912行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def make_incrementor(n):
+
<syntaxhighlight lang="python3">>>> def make_incrementor(n):
 
...    return lambda x: x + n
 
...    return lambda x: x + n
 
...
 
...
&gt;&gt;&gt; f = make_incrementor(42)
+
>>> f = make_incrementor(42)
&gt;&gt;&gt; f(0)
+
>>> f(0)
 
42
 
42
&gt;&gt;&gt; f(1)
+
>>> f(1)
43</pre>
+
43</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The above example uses a lambda expression to return a function. Another use
+
上面的例子使用一个 lambda 表达式来返回一个函数。 另一个用途是传递一个小函数作为参数:
is to pass a small function as an argument:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,084行: 第930行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
+
<syntaxhighlight lang="python3">>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
&gt;&gt;&gt; pairs.sort(key=lambda pair: pair[1])
+
>>> pairs.sort(key=lambda pair: pair[1])
&gt;&gt;&gt; pairs
+
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]</pre>
+
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]</syntaxhighlight>
  
 
</div>
 
</div>
第1,097行: 第943行:
  
 
<span id="tut-docstrings"></span>
 
<span id="tut-docstrings"></span>
=== <span class="section-number">4.7.7. </span>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 解析器不会从 Python 中的多行字符串文字中去除缩进,因此处理文档的工具必须根据需要去除缩进。 这是使用以下约定完成的。 字符串的第一行 ''之后的第一个非空行'' 决定了整个文档字符串的缩进量。 (我们不能使用第一行,因为它通常与字符串的开始引号相邻,因此它的缩进在字符串文字中不明显。)然后从字符串的所有行的开头去除与此缩进“等效”的空白. 缩进较少的行不应出现,但如果出现,则应去除所有前导空格。 扩展选项卡后应测试空格的等效性(通常为 8 个空格)。
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 &quot;equivalent&quot; 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:
+
这是多行文档字符串的示例:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,131行: 第959行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def my_function():
+
<syntaxhighlight lang="python3">>>> def my_function():
...    &quot;&quot;&quot;Do nothing, but document it.
+
...    """Do nothing, but document it.
 
...
 
...
 
...    No, really, it doesn't do anything.
 
...    No, really, it doesn't do anything.
...    &quot;&quot;&quot;
+
...    """
 
...    pass
 
...    pass
 
...
 
...
&gt;&gt;&gt; print(my_function.__doc__)
+
>>> print(my_function.__doc__)
 
Do nothing, but document it.
 
Do nothing, but document it.
  
     No, really, it doesn't do anything.</pre>
+
     No, really, it doesn't do anything.</syntaxhighlight>
  
 
</div>
 
</div>
第1,151行: 第979行:
  
 
<span id="tut-annotations"></span>
 
<span id="tut-annotations"></span>
=== <span class="section-number">4.7.8. </span>Function Annotations ===
+
=== 4.7.8. 函数注解 ===
  
[[../../reference/compound_stmts#function|<span class="std std-ref">Function annotations</span>]] are completely optional metadata
+
[[../../reference/compound_stmts#function|函数注释]]是关于用户定义函数使用的类型的完全可选的元数据信息(参见<span id="index-6" class="target"></span>[https://www.python.org/dev/peps/pep-3107 PEP 3107]<span id="index-7" class="target"></span>[https://www.python.org/dev/peps/pep-0484 PEP 484] 了解更多信息)。
information about the types used by user-defined functions (see <span id="index-6" class="target"></span>[https://www.python.org/dev/peps/pep-3107 '''PEP 3107'''] and
 
<span id="index-7" class="target"></span>[https://www.python.org/dev/peps/pep-0484 '''PEP 484'''] for more information).
 
  
[[../../glossary#term-function-annotation|<span class="xref std std-term">Annotations</span>]] are stored in the <code>__annotations__</code>
+
[[../../glossary#term-function-annotation|Annotations]] 作为字典存储在函数的 <code>__annotations__</code> 属性中,对函数的任何其他部分没有影响。 参数注释由参数名称后的冒号定义,后跟计算注释值的表达式。 返回注释由文字 <code>-&gt;</code> 定义,后跟表达式,位于参数列表和表示 [[../../reference/compound_stmts#def|def]] 语句结尾的冒号之间。 以下示例具有必需参数、可选参数和带注释的返回值:
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 <code>-&gt;</code>, followed by an expression, between the parameter
 
list and the colon denoting the end of the [[../../reference/compound_stmts#def|<code>def</code>]] statement. The
 
following example has a positional argument, a keyword argument, and the return
 
value annotated:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,170行: 第989行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def f(ham: str, eggs: str = 'eggs') -&gt; str:
+
<syntaxhighlight lang="python3">>>> def f(ham: str, eggs: str = 'eggs') -> str:
...    print(&quot;Annotations:&quot;, f.__annotations__)
+
...    print("Annotations:", f.__annotations__)
...    print(&quot;Arguments:&quot;, ham, eggs)
+
...    print("Arguments:", ham, eggs)
 
...    return ham + ' and ' + eggs
 
...    return ham + ' and ' + eggs
 
...
 
...
&gt;&gt;&gt; f('spam')
+
>>> f('spam')
Annotations: {'ham': &lt;class 'str'&gt;, 'return': &lt;class 'str'&gt;, 'eggs': &lt;class 'str'&gt;}
+
Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
 
Arguments: spam eggs
 
Arguments: spam eggs
'spam and eggs'</pre>
+
'spam and eggs'</syntaxhighlight>
  
 
</div>
 
</div>
第1,190行: 第1,009行:
  
 
<span id="tut-codingstyle"></span>
 
<span id="tut-codingstyle"></span>
== <span class="section-number">4.8. </span>Intermezzo: Coding Style ==
+
== 4.8. 间奏曲:编码风格 ==
  
Now that you are about to write longer, more complex pieces of Python, it is a
+
现在您将要编写更长、更复杂的 Python 片段,现在是讨论 ''编码风格'' 的好时机。 大多数语言都可以用不同的风格编写(或更简洁,''格式化''); 有些比其他的更具可读性。 让其他人更容易阅读你的代码总是一个好主意,采用一个好的编码风格对此有很大帮助。
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, <span id="index-9" class="target"></span>[https://www.python.org/dev/peps/pep-0008 '''PEP 8'''] has emerged as the style guide that most projects adhere to;
+
对于 Python,<span id="index-9" class="target"></span>[https://www.python.org/dev/peps/pep-0008 PEP 8] 已经成为大多数项目遵循的风格指南; 它提倡一种非常易读且赏心悦目的编码风格。 每个 Python 开发人员都应该在某个时候阅读它; 以下是为您提取的最重要的要点:
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:
 
  
 
<ul>
 
<ul>
<li><p>Use 4-space indentation, and no tabs.</p>
+
<li><p>使用 4 个空格缩进,并且没有制表符。</p>
<p>4 spaces are a good compromise between small indentation (allows greater
+
<p>4 个空格是小缩进(允许更大的嵌套深度)和大缩进(更容易阅读)之间的一个很好的折衷。 选项卡会引起混乱,最好将其排除在外。</p></li>
nesting depth) and large indentation (easier to read). Tabs introduce
+
<li><p>换行,使其不超过 79 个字符。</p>
confusion, and are best left out.</p></li>
+
<p>这有助于使用小显示器的用户,并可以在较大的显示器上并排放置多个代码文件。</p></li>
<li><p>Wrap lines so that they don't exceed 79 characters.</p>
+
<li><p>使用空行来分隔函数和类,以及函数内部的较大代码块。</p></li>
<p>This helps users with small displays and makes it possible to have several
+
<li><p>如果可能,将注释放在他们自己的一行中。</p></li>
code files side-by-side on larger displays.</p></li>
+
<li><p>使用文档字符串。</p></li>
<li><p>Use blank lines to separate functions and classes, and larger blocks of
+
<li><p>在运算符周围和逗号后使用空格,但不要直接在括号结构内使用:<code>a = f(1, 2) + g(3, 4)</code></p></li>
code inside functions.</p></li>
+
<li><p>一致地命名您的类和函数; 约定是对类使用 <code>UpperCamelCase</code>,对函数和方法使用 <code>lowercase_with_underscores</code>。 始终使用 <code>self</code> 作为第一个方法参数的名称(有关类和方法的更多信息,请参阅 [[../classes#tut-firstclasses|类的第一眼]] )。</p></li>
<li><p>When possible, put comments on a line of their own.</p></li>
+
<li><p>如果您的代码打算在国际环境中使用,请不要使用花哨的编码。 在任何情况下,Python 的默认值、UTF-8 甚至纯 ASCII 都效果最好。</p></li>
<li><p>Use docstrings.</p></li>
+
<li><p>同样,如果使用不同语言的人阅读或维护代码的可能性很小,则不要在标识符中使用非 ASCII 字符。</p></li></ul>
<li><p>Use spaces around operators and after commas, but not directly inside
 
bracketing constructs: <code>a = f(1, 2) + g(3, 4)</code>.</p></li>
 
<li><p>Name your classes and functions consistently; the convention is to use
 
<code>UpperCamelCase</code> for classes and <code>lowercase_with_underscores</code> for functions
 
and methods. Always use <code>self</code> as the name for the first method argument
 
(see [[../classes#tut-firstclasses|<span class="std std-ref">A First Look at Classes</span>]] for more on classes and methods).</p></li>
 
<li><p>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.</p></li>
 
<li><p>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.</p></li></ul>
 
  
Footnotes
+
脚注
  
 
; <span class="brackets">[[#id1|1]]</span>
 
; <span class="brackets">[[#id1|1]]</span>
: 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).
+
: 实际上,通过对象引用''调用'' 会是一个更好的描述,因为如果传递了一个可变对象,调用者将看到被调用者对其所做的任何更改(插入到列表中的项目)。
  
  
 
</div>
 
</div>
 +
 +
</div>
 +
<div class="clearer">
 +
 +
  
 
</div>
 
</div>
  
[[Category:Python 3.9 中文文档]]
+
[[Category:Python 3.9 文档]]

2021年10月31日 (日) 04:54的最新版本

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 ... 序列可替代其他语言中的 switchcase 语句。


4.2. for声明

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

在迭代同一集合时修改集合的代码可能很难正确。 相反,循环遍历集合的副本或创建新集合通常更直接:

# 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. 这范围() 功能

如果您确实需要迭代一系列数字,内置函数 range() 会派上用场。 它生成算术级数:

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

给定的终点永远不是生成序列的一部分; range(10) 生成 10 个值,即长度为 10 的序列的项目的合法索引。 可以让范围从另一个数字开始,或者指定不同的增量(甚至是负数;有时这称为“步长”):

>>> list(range(5, 10))
[5, 6, 7, 8, 9]

>>> list(range(0, 10, 3))
[0, 3, 6, 9]

>>> list(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(10)
range(0, 10)

在许多方面,range() 返回的对象表现得好像它是一个列表,但实际上它不是。 它是一个对象,当您对其进行迭代时,它会返回所需序列的连续项目,但它并没有真正生成列表,从而节省了空间。

我们说这样的对象是 iterable,也就是说,适合作为函数和构造的目标,这些函数和构造期望从中获得连续的项目,直到供应耗尽。 我们已经看到 for 语句就是这样一种结构,而一个采用可迭代对象的函数的例子是 sum()

>>> sum(range(4))  # 0 + 1 + 2 + 3
6

稍后我们将看到更多返回可迭代对象并将可迭代对象作为参数的函数。 在数据结构一章中,我们将更详细地讨论list()


4.4. break和continue声明,以及else关于循环的条款

break 语句,就像在 C 中一样,从最内层的 forwhile 循环中跳出。

循环语句可能有一个 else 子句; 当循环因可迭代对象耗尽(使用 for)或条件变为假(使用 while)而终止时执行,但不会在循环由 终止时执行]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

(是的,这是正确的代码。 仔细观察:else 子句属于 for 循环,not if 语句。)

当与循环一起使用时,else 子句与 try 语句的 else 子句的共同点多于与 if 语句的共同点语句:try 语句的 else 子句在没有异常发生时运行,循环的 else 子句在没有 break 发生时运行。 有关 try 语句和异常的更多信息,请参阅 处理异常

continue 语句也是从 C 中借来的,继续循环的下一次迭代:

>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found an odd number", num)
...
Found an even number 2
Found an odd number 3
Found an even number 4
Found an odd number 5
Found an even number 6
Found an odd number 7
Found an even number 8
Found an odd number 9

4.5. pass声明

pass 语句什么也不做。 它可以在语法上需要语句但程序不需要操作时使用。 例如:

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

这通常用于创建最小类:

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

另一个可以使用 pass 的地方是在您处理新代码时作为函数或条件体的占位符,让您可以在更抽象的层次上继续思考。 pass 被默默忽略:

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

4.6. 定义函数

我们可以创建一个函数,将斐波那契数列写入任意边界:

>>> def fib(n):    # write Fibonacci series up to n
...     """Print a Fibonacci series up to n."""
...     a, b = 0, 1
...     while a < n:
...         print(a, end=' ')
...         a, b = b, a+b
...     print()
...
>>> # Now call the function we just defined:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

关键字 def 引入了函数 definition。 它后面必须是函数名和带括号的形式参数列表。 构成函数体的语句从下一行开始,并且必须缩进。

函数体的第一条语句可以选择是字符串文字; 此字符串文字是函数的文档字符串,或 docstring。 (有关文档字符串的更多信息可以在 文档字符串 部分找到。)有一些工具可以使用文档字符串自动生成在线或打印文档,或者让用户以交互方式浏览代码; 在您编写的代码中包含文档字符串是一种很好的做法,因此请养成习惯。

函数的 execution 引入了一个用于函数局部变量的新符号表。 更准确地说,函数中的所有变量赋值都将值存储在本地符号表中; 而变量引用首先查看局部符号表,然后是封闭函数的局部符号表,然后是全局符号表,最后是内置名称表。 因此,全局变量和封闭函数的变量不能在函数内直接赋值(除非对于全局变量,在 global 语句中命名,或者对于封闭函数的变量,在 语句中命名) ]nonlocal 语句),尽管它们可能会被引用。

函数调用的实际参数(arguments)在被调用函数的局部符号表中被引入; 因此,参数是使用 按值 调用传递的(其中 始终是对象 引用 ,而不是对象的值)。 1 当一个函数调用另一个函数或递归调用自身时,会为该调用创建一个新的本地符号表。

函数定义将函数名称与当前符号表中的函数对象相关联。 解释器将该名称指向的对象识别为用户定义的函数。 其他名称也可以指向相同的函数对象,也可以用于访问该函数:

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

来自其他语言,您可能反对 fib 不是函数而是过程,因为它不返回值。 事实上,即使没有 return 语句的函数也会返回一个值,尽管它相当无聊。 该值称为 None(它是一个内置名称)。 如果写入值 None 是唯一写入的值,则它通常会被解释器抑制。 如果你真的想使用 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 特性:

  • return 语句从函数返回一个值。 return 没有表达式参数返回 None。 从函数的末尾脱落也会返回 None
  • 语句 result.append(a) 调用列表对象 result方法 。 方法是“属于”对象的函数,名为 obj.methodname,其中 obj 是某个对象(这可能是一个表达式),而 methodname 是名称由对象的类型定义的方法。 不同的类型定义不同的方法。 不同类型的方法可以具有相同的名称而不会引起歧义。 (可以定义自己的对象类型和方法,使用 classes,参见 Classes)示例中的方法 append() 是为列表对象定义的; 它在列表的末尾添加一个新元素。 在本例中,它等效于 result = result + [a],但效率更高。


4.7. 有关定义函数的更多信息

也可以定义具有可变数量参数的函数。 共有三种形式,可以组合使用。

4.7.1. 默认参数值

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

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)

可以通过多种方式调用此函数:

  • 仅给出强制性参数:ask_ok('Do you really want to quit?')
  • 给出可选参数之一:ask_ok('OK to overwrite the file?', 2)
  • 甚至给出所有参数:ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')

此示例还引入了 in 关键字。 这将测试序列是否包含某个值。

默认值在 defining 作用域中的函数定义点计算,因此

i = 5

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

i = 6
f()

将打印 5

重要警告: 默认值仅评估一次。 当默认值是可变对象(例如列表、字典或大多数类的实例)时,这会有所不同。 例如,以下函数在后续调用中累积传递给它的参数:

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

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

这将打印

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

如果您不希望在后续调用之间共享默认值,则可以编写如下函数:

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

4.7.2. 关键字参数

也可以使用 kwarg=value 形式的 关键字参数 调用函数。 例如,以下函数:

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

接受一个必需参数 (voltage) 和三个可选参数(stateactiontype)。 可以通过以下任何一种方式调用此函数:

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

但以下所有调用都是无效的:

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

在函数调用中,关键字参数必须跟在位置参数之后。 传递的所有关键字参数必须与函数接受的参数之一匹配(例如 actor 不是 parrot 函数的有效参数),它们的顺序并不重要。 这也包括非可选参数(例如 parrot(voltage=1000) 也有效)。 任何参数都不能多次接收一个值。 这是一个由于此限制而失败的示例:

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

当存在 **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])

可以这样调用:

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

当然它会打印:

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

请注意,打印关键字参数的顺序保证与它们在函数调用中提供的顺序相匹配。


4.7.3. 特殊参数

默认情况下,参数可以通过位置或显式通过关键字传递给 Python 函数。 为了可读性和性能,限制参数的传递方式是有意义的,这样开发人员只需查看函数定义即可确定项目是按位置、按位置或关键字还是按关键字传递。

函数定义可能如下所示:

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
      -----------    ----------     ----------
        |             |                  |
        |        Positional or keyword   |
        |                                - Keyword only
         -- Positional only

其中 /* 是可选的。 如果使用,这些符号通过参数如何传递给函数来指示参数的类型:仅位置、位置或关键字和仅关键字。 关键字参数也称为命名参数。

4.7.3.1. 位置或关键字参数

如果函数定义中不存在 /*,则可以通过位置或关键字将参数传递给函数。


4.7.3.2. 仅位置参数

更详细地看一下,可以将某些参数标记为 positional-only。 如果是positional-only,参数的顺序很重要,不能通过关键字传递参数。 仅位置参数放置在 /(正斜杠)之前。 / 用于在逻辑上将仅位置参数与其余参数分开。 如果函数定义中没有 /,则没有仅位置参数。

/ 后面的参数可以是 positional-or-keywordkeyword-only


4.7.3.3. 仅关键字参数

要将参数标记为 keyword-only,指示参数必须通过关键字参数传递,请在参数列表中第一个 keyword-only 参数之前放置一个 * .


4.7.3.4. 函数示例

考虑以下示例函数定义,重点关注标记 /*

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

第一个函数定义,standard_arg,最熟悉的形式,对调用约定没有限制,参数可以通过位置或关键字传递:

>>> standard_arg(2)
2

>>> standard_arg(arg=2)
2

第二个函数 pos_only_arg 仅限于使用位置参数,因为函数定义中有一个 /

>>> pos_only_arg(1)
1

>>> pos_only_arg(arg=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: pos_only_arg() got some positional-only arguments passed as keyword arguments: 'arg'

第三个函数 kwd_only_args 只允许关键字参数,如函数定义中的 * 所示:

>>> kwd_only_arg(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: kwd_only_arg() takes 0 positional arguments but 1 was given

>>> kwd_only_arg(arg=3)
3

最后一个在同一个函数定义中使用所有三个调用约定:

>>> combined_example(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
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 "<stdin>", line 1, in <module>
TypeError: combined_example() got some positional-only arguments passed as keyword arguments: 'pos_only'

最后,考虑这个函数定义,它在位置参数 name 和以 name 作为键的 **kwds 之间存在潜在冲突:

def foo(name, **kwds):
    return 'name' in kwds

没有可能的调用使其返回 True,因为关键字 'name' 将始终绑定到第一个参数。 例如:

>>> foo(1, **{'name': 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got multiple values for argument 'name'
>>>

但是使用 /(仅位置参数),这是可能的,因为它允许 name 作为位置参数和 'name' 作为关键字参数中的键:

def foo(name, /, **kwds):
    return 'name' in kwds
>>> foo(1, **{'name': 2})
True

换句话说,仅位置参数的名称可以在 **kwds 中使用而不会产生歧义。


4.7.3.5. 回顾

用例将确定在函数定义中使用哪些参数:

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

作为指导:

  • 如果您希望参数的名称对用户不可用,请使用 positional-only。 当参数名称没有实际意义时,如果您想在调用函数时强制执行参数的顺序,或者您需要采用一些位置参数和任意关键字,这将非常有用。
  • 当名称有意义并且函数定义通过明确的名称更易于理解或您想防止用户依赖于传递的参数的位置时,使用仅关键字。
  • 对于 API,如果将来修改了参数名称,请使用 positional-only 来防止破坏 API 更改。


4.7.4. 任意参数列表

最后,最不常用的选项是指定可以使用任意数量的参数调用函数。 这些参数将包含在一个元组中(参见 元组和序列 )。 在可变数量的参数之前,可能会出现零个或多个正常参数。

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

通常,这些 variadic 参数将位于形式参数列表的最后,因为它们会收集传递给函数的所有剩余输入参数。 出现在 *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. 解包参数列表

当参数已经在列表或元组中但需要为需要单独位置参数的函数调用解包时,会发生相反的情况。 例如,内置的 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]

以同样的方式,字典可以使用 ** 运算符传递关键字参数:

>>> 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 表达式

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

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

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

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

4.7.7. 文档字符串

以下是关于文档字符串的内容和格式的一些约定。

第一行应始终是对象用途的简短摘要。 为简洁起见,它不应明确说明对象的名称或类型,因为它们可以通过其他方式获得(除非名称恰好是描述函数操作的动词)。 此行应以大写字母开头并以句点结尾。

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

Python 解析器不会从 Python 中的多行字符串文字中去除缩进,因此处理文档的工具必须根据需要去除缩进。 这是使用以下约定完成的。 字符串的第一行 之后的第一个非空行 决定了整个文档字符串的缩进量。 (我们不能使用第一行,因为它通常与字符串的开始引号相邻,因此它的缩进在字符串文字中不明显。)然后从字符串的所有行的开头去除与此缩进“等效”的空白. 缩进较少的行不应出现,但如果出现,则应去除所有前导空格。 扩展选项卡后应测试空格的等效性(通常为 8 个空格)。

这是多行文档字符串的示例:

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

    No, really, it doesn't do anything.

4.7.8. 函数注解

函数注释是关于用户定义函数使用的类型的完全可选的元数据信息(参见PEP 3107PEP 484 了解更多信息)。

Annotations 作为字典存储在函数的 __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. 间奏曲:编码风格

现在您将要编写更长、更复杂的 Python 片段,现在是讨论 编码风格 的好时机。 大多数语言都可以用不同的风格编写(或更简洁,格式化); 有些比其他的更具可读性。 让其他人更容易阅读你的代码总是一个好主意,采用一个好的编码风格对此有很大帮助。

对于 Python,PEP 8 已经成为大多数项目遵循的风格指南; 它提倡一种非常易读且赏心悦目的编码风格。 每个 Python 开发人员都应该在某个时候阅读它; 以下是为您提取的最重要的要点:

  • 使用 4 个空格缩进,并且没有制表符。

    4 个空格是小缩进(允许更大的嵌套深度)和大缩进(更容易阅读)之间的一个很好的折衷。 选项卡会引起混乱,最好将其排除在外。

  • 换行,使其不超过 79 个字符。

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

  • 使用空行来分隔函数和类,以及函数内部的较大代码块。

  • 如果可能,将注释放在他们自己的一行中。

  • 使用文档字符串。

  • 在运算符周围和逗号后使用空格,但不要直接在括号结构内使用:a = f(1, 2) + g(3, 4)

  • 一致地命名您的类和函数; 约定是对类使用 UpperCamelCase,对函数和方法使用 lowercase_with_underscores。 始终使用 self 作为第一个方法参数的名称(有关类和方法的更多信息,请参阅 类的第一眼 )。

  • 如果您的代码打算在国际环境中使用,请不要使用花哨的编码。 在任何情况下,Python 的默认值、UTF-8 甚至纯 ASCII 都效果最好。

  • 同样,如果使用不同语言的人阅读或维护代码的可能性很小,则不要在标识符中使用非 ASCII 字符。

脚注

1
实际上,通过对象引用调用 会是一个更好的描述,因为如果传递了一个可变对象,调用者将看到被调用者对其所做的任何更改(插入到列表中的项目)。