4. More Control Flow Tools 控制流工具
Besides the while
statement just introduced, Python knows the usual control flow statements known from other languages, with some twists.
除了介紹的 while
語(yǔ)句知染, Python從其他語(yǔ)言中借鑒了常用的控制流語(yǔ)句双霍,并做了部分修改报破。
4.1. if
Statements If 語(yǔ)句
Perhaps the most well-known statement type is the if
statement. For example:
也許就著名的語(yǔ)句類型就是if
語(yǔ)句了续语。例如:
>>> 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.
這里可以有0個(gè)或多個(gè) elif
, 并且 else
語(yǔ)句也是可選的犬第。 關(guān)鍵字 elif
是 else if
的縮寫诀姚,這樣可以有效的避免過(guò)多的縮進(jìn)。 一個(gè)if ... elif ... elif ...
語(yǔ)句是其他語(yǔ)言中 switch 或 case
語(yǔ)句的替代品妓湘。
4.2. for
Statements For 語(yǔ)句
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
語(yǔ)句和你在C或Pascal語(yǔ)言中使用的有點(diǎn)不一樣查蓉。 不像Pascal中一直是算數(shù)級(jí)數(shù)的迭代,或者C中允許用戶定義迭代的步長(zhǎng)和停止循環(huán)條件榜贴,Python中的for
語(yǔ)句是在按元素序列(字符串或列表)中的順序迭代豌研。例如(沒(méi)有語(yǔ)義雙關(guān)):
>>> # Measure some strings:
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
... print(w, len(w))
...
cat 3
window 6
defenestrate 12
If you need to modify the sequence you are iterating over while inside the loop (for example to duplicate selected items), it is recommended that you first make a copy. Iterating over a sequence does not implicitly make a copy. The slice notation makes this especially convenient:
如果你想要在循環(huán)迭代中修改列表(例如重復(fù)選中的元素),建議你首先做一個(gè)備份。序列中的迭代不會(huì)做隱性備份鹃共,切片法讓這個(gè)很簡(jiǎn)單:
>>> for w in words[:]: # Loop over a slice copy of the entire list.
... if len(w) > 6:
... words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']
With for w in words:
, the example would attempt to create an infinite list, inserting defenestrate
over and over again.
相對(duì)于 or w in words:
, 這個(gè)例子將會(huì)創(chuàng)建一個(gè)無(wú)限的列表鬼佣,一直重復(fù)插入'defenestrate'。(譯者注:因?yàn)?code>insert操作的是word列表本身霜浴,如果一直循環(huán)迭代元素的也是word本身晶衷,就會(huì)陷入死循環(huán)。用了切片來(lái)復(fù)制一個(gè)word列表來(lái)循環(huán)迭代阴孟,這個(gè)時(shí)候新插入的元素就不會(huì)影響到迭代了晌纫。)
4.3. The range()
Function range()
函數(shù)
If you do need to iterate over a sequence of numbers, the built-in function range()
comes in handy. It generates arithmetic progressions:
如果你需要在數(shù)字序列中迭代,內(nèi)置的函數(shù)range()
就可以順手拈來(lái)永丝。下面的例如可以產(chǎn)生一個(gè)算數(shù)級(jí)數(shù):
>>> 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’):
這個(gè)給定的結(jié)束點(diǎn)從來(lái)都不是產(chǎn)生序列的一部分锹漱。range()
產(chǎn)生10個(gè)值,一個(gè)長(zhǎng)度是10的序列中元素合法的下標(biāo)类溢×枋撸可以讓這個(gè)范圍起始于另外一個(gè)號(hào)碼,或者指定一個(gè)不同的增長(zhǎng)(甚至是負(fù)數(shù)增長(zhǎng)闯冷,有時(shí)也叫做步長(zhǎng)
):
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()
來(lái)迭代遍歷序列的下標(biāo):
>>> 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()
函數(shù)是更方便的蛇耀,可以查看Looping Techniques:循環(huán)的技巧.
A strange thing happens if you just print a range:
當(dāng)你打印一個(gè)range時(shí),會(huì)發(fā)生奇怪的事情:
>>> 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()
返回的對(duì)象表現(xiàn)得它好像是一個(gè)列表纺涤,但實(shí)際上它不是。它是當(dāng)你迭代遍歷一個(gè)期望的序列中連續(xù)的元素時(shí)返回的一個(gè)對(duì)象抠忘,但并沒(méi)有真正的創(chuàng)建一個(gè)列表撩炊,從而節(jié)省空間。
We say such an object is iterable, that is, suitable as a target for functions and constructs that expect something from which they can obtain successive items until the supply is exhausted. We have seen that the for
statement is such an iterator. The function list()
is another; it creates lists from iterables:
我們所說(shuō)的這個(gè)對(duì)象就是迭代器: 很適合作為那些期望獲得連續(xù)的元素直到最后的函數(shù)和構(gòu)造器的目標(biāo)崎脉。我們可以看出for
語(yǔ)句就是這個(gè)迭代器拧咳,list()
函數(shù)就是另外一個(gè),它從迭代器中創(chuàng)建列表:
>>> list(range(5))
[0, 1, 2, 3, 4]
Later we will see more functions that return iterables and take iterables as argument.
稍后我們將會(huì)看到更多函數(shù)返回迭代器并將迭代器作為參數(shù)囚灼。
4.4. break
and continue
Statements, and else
Clauses on Loops
循環(huán)中的break
和continue
語(yǔ)句骆膝,以及 else
條款
The break
statement, like in C, breaks out of the innermost enclosing for
or while
loop.
break
語(yǔ)句,跟C中的一樣灶体,跳出for
和 while
最里面的一層循環(huán)阅签。
Loop statements may have an else
clause; it is executed when the loop terminates through exhaustion of the list (with for
) or when the condition becomes false (with while
), but not when the loop is terminated by a break
statement. This is exemplified by the following loop, which searches for prime numbers:
循環(huán)語(yǔ)句中也可以有一個(gè)else
分支。當(dāng)循環(huán)遍歷完列表后中斷或循環(huán)條件為假時(shí)就會(huì)執(zhí)行蝎抽,但不是當(dāng)循環(huán)是通過(guò)break
終止的時(shí)候政钟。下面查找質(zhì)數(shù)的循環(huán)就是例證:
>>> 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循環(huán)的精算,不是if語(yǔ)句)
When used with a loop, the else
clause has more in common with the else
clause of a try
statement than it does that of if
statements: a try
statement’s else
clause runs when no exception occurs, and a loop’s else
clause runs when no break
occurs. For more on the try
statement and exceptions, see Handling Exceptions.
當(dāng)使用一個(gè)循環(huán)的時(shí)候,else
條款跟 try
語(yǔ)句的else
有更多的共同點(diǎn)层坠,而不是 if
中的殖妇。當(dāng)沒(méi)有異常發(fā)生的時(shí)候,try
語(yǔ)句中的else
條款運(yùn)行破花,當(dāng)沒(méi)有break
發(fā)生的時(shí)候谦趣,循環(huán)中的else
條款執(zhí)行。更多關(guān)于try
語(yǔ)句和異常座每,請(qǐng)查看 Handling Exceptions:處理異常.
The continue
statement, also borrowed from C, continues with the next iteration of the loop:
continue
語(yǔ)句前鹅,也是借鑒了C中的,在循環(huán)中繼續(xù)下一次迭代:
>>> for num in range(2, 10):
... if num % 2 == 0:
... print("Found an even number", num)
... continue
... print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9
4.5. pass
Statements Pass 語(yǔ)句
The pass
statement does nothing. It can be used when a statement is required syntactically but the program requires no action. For example:
pass
語(yǔ)句不做任何事峭梳。當(dāng)僅僅是一個(gè)語(yǔ)句的語(yǔ)法要求但程序并沒(méi)有任何操作要求時(shí)舰绘,可以使用它.例如:
>>> while True:
... pass # Busy-wait for keyboard interrupt (Ctrl+C)
...
This is commonly used for creating minimal classes:
這個(gè)也經(jīng)常用來(lái)創(chuàng)建一個(gè)最小的類:
>>> 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:
另外一個(gè)用到pass
的地方就是當(dāng)你在寫新的代碼的時(shí)候,可以用它為函數(shù)或條件體占位葱椭,這樣允許你在一個(gè)更加抽象的水平來(lái)繼續(xù)你的思考捂寿。pass
就會(huì)被默默的忽略:
>>> def initlog(*args):
... pass # Remember to implement this!
...
4.6. Defining Functions 定義函數(shù)
We can create a function that writes the Fibonacci series to an arbitrary boundary:
我們可以創(chuàng)建一個(gè)函數(shù)來(lái)寫出隨意邊界的斐波那契數(shù)列:
>>> 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.
關(guān)鍵字def
介紹了一個(gè)函數(shù)的定義。它后面必須跟著函數(shù)名和括號(hào)內(nèi)的形參數(shù)列表孵运。組成函數(shù)體的語(yǔ)句在下一行開(kāi)始秦陋,并且必須縮進(jìn)。
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.
函數(shù)體的第一個(gè)語(yǔ)句可以選擇是一個(gè)字符串常量治笨。這個(gè)字符串常量是這個(gè)函數(shù)的文檔字符串(更多關(guān)于文檔字符串可以在[Documentation Strings 文檔字符串]節(jié)選查看(https://docs.python.org/3/tutorial/controlflow.html#tut-docstrings))驳概。這些是用文檔字符串來(lái)自動(dòng)生成線上或打印文檔,或讓用戶通過(guò)瀏覽代碼來(lái)進(jìn)行交互的工具旷赖。寫代碼的時(shí)候包含文檔字符串是一個(gè)很好的實(shí)踐顺又,所以請(qǐng)把這個(gè)作為一個(gè)習(xí)慣來(lái)看待。
The execution of a function introduces a new symbol table used for the local variables of the function. More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names. Thus, global variables cannot be directly assigned a value within a function (unless named in a global
statement), although they may be referenced.
函數(shù)的執(zhí)行引入了用戶幻術(shù)局部變量的新字符表等孵。更準(zhǔn)確的說(shuō)稚照,函數(shù)中的所有變量
賦值都存儲(chǔ)在本地符號(hào)表中。而變量引用首先在本地符號(hào)表查找流济,然后是在關(guān)閉本函數(shù)的本地符號(hào)表去查找锐锣,然后是在全局符號(hào)表,最后是在內(nèi)置名稱表中查找绳瘟。因此雕憔,盡管可以引用全局變量,但是不能直接在函數(shù)賦值(除非在全局變量中命名)糖声。
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.
當(dāng)一個(gè)函數(shù)被調(diào)用的時(shí)候斤彼,函數(shù)調(diào)用的實(shí)參會(huì)被引入被調(diào)用函數(shù)的本地符號(hào)表分瘦。因此,參數(shù)會(huì)通過(guò)值調(diào)用來(lái)傳遞的(這個(gè)值始終是一個(gè)對(duì)象的引用琉苇,而不是對(duì)象的值)嘲玫。當(dāng)一個(gè)函數(shù)調(diào)用另外一個(gè)函數(shù),一個(gè)新的本地符號(hào)表將會(huì)為這個(gè)調(diào)用而創(chuàng)建并扇。
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:
函數(shù)定義在當(dāng)前符號(hào)表中引入了函數(shù)名去团。函數(shù)名的值具讓解釋器將其識(shí)別為用戶定義函數(shù)的類型。
>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89
Coming from other languages, you might object that fib
is not a function but a procedure since it doesn’t return a value. In fact, even functions without a return
statement do return a value, albeit a rather boring one. This value is called None
(it’s a built-in name). Writing the value None
is normally suppressed by the interpreter if it would be the only value written. You can see it if you really want to using print()
:
從其他語(yǔ)言來(lái)看穷蛹,你可能認(rèn)為fib
不是一個(gè)函數(shù)土陪,而是一個(gè)過(guò)程,因?yàn)樗鼪](méi)有返回值肴熏。事實(shí)上鬼雀,即使函數(shù)沒(méi)有return語(yǔ)句,也始終會(huì)返回一個(gè)值蛙吏,即使是個(gè)沒(méi)有很無(wú)聊的值源哩。這個(gè)值被稱為 None
(這是一個(gè)內(nèi)置的名稱)。如果None
是唯一被打印的值鸦做,解釋器通常是抑制打印輸出的(譯者注:也就是省略打印None)励烦。如果你真的想要看看你可以使用print()
:
>>> fib(0) #這個(gè)按回車之后解釋器沒(méi)有任何輸出
>>> print(fib(0)) #實(shí)際這個(gè)函數(shù)的返回值是一個(gè)None
None
It is simple to write a function that returns a list of the numbers of the Fibonacci series, instead of printing it:
很容易寫一個(gè)函數(shù)來(lái)返回斐波那契數(shù)列列表的函數(shù),來(lái)替代直接打印輸出:
>>> 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:
這個(gè)例子泼诱,跟往常一樣崩侠,演示了Python一些新的特征:
The
return
statement returns with a value from a function.return
without an expression argument returnsNone
. Falling off the end of a function also returnsNone
.return
語(yǔ)句從函數(shù)中返回一個(gè)值。return
語(yǔ)句中沒(méi)有任何表達(dá)式參數(shù)將會(huì)返回None坷檩。在函數(shù)的最后前運(yùn)行出錯(cuò)也會(huì)返回None。The statement
result.append(a)
calls a method of the list objectresult
. A method is a function that ‘belongs’ to an object and is namedobj.methodname
, whereobj
is some object (this may be an expression), andmethodname
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 methodappend()
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 toresult = result + [a]
, but more efficient.result.append(a)
語(yǔ)句調(diào)用了列表對(duì)象result
的方法改抡。一個(gè)方法就是一個(gè)屬于一個(gè)對(duì)象的函數(shù)矢炼,命名為obj.methodname
,這個(gè)obj就是對(duì)象(這里也可以是一個(gè)表達(dá)式)阿纤,methodname就是這個(gè)對(duì)象類型定義的方法名句灌。不同的類型定義不同的方法。不同的方法可以有同樣的命名且不引起歧義欠拾。(你可以用類來(lái)定義你自己的對(duì)象類型和方法胰锌,具體查看Classes) 這個(gè)例子中展示的方法append()
就是列表對(duì)象定義的。它在列表的末尾添加一個(gè)新的元素藐窄。在這個(gè)例子中资昧,它等價(jià)于result = result + [a]
, 當(dāng)更高效。
4.7. More on Defining Functions 更多關(guān)于定義函數(shù)
It is also possible to define functions with a variable number of arguments. There are three forms, which can be combined.
也可以定義一個(gè)參數(shù)數(shù)量可變的函數(shù)荆忍。這里有三種形式格带,可以組合使用:
4.7.1. Default Argument Values 默認(rèn)參數(shù)值
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:
最有用的形式就是指定一個(gè)或多個(gè)參數(shù)的默認(rèn)值撤缴。這樣創(chuàng)建的函數(shù)運(yùn)行在被調(diào)用的時(shí)候的參數(shù)比定義要求的個(gè)數(shù)更少。例如:
def ask_ok(prompt, retries=4, reminder='Please try again!'):
while True:
ok = input(prompt)
if ok in ('y', 'ye', 'yes'):
return True
if ok in ('n', 'no', 'nop', 'nope'):
return False
retries = retries - 1
if retries < 0:
raise ValueError('invalid user response')
print(reminder)
This function can be called in several ways:
- giving only the mandatory argument:
ask_ok('Do you really want to quit?')
- giving one of the optional arguments:
ask_ok('OK to overwrite the file?', 2)
- or even giving all arguments:
ask_ok('OK to overwrite the file?', 2, 'Come on, only yesor no!')
這個(gè)函數(shù)可以通過(guò)幾種方式調(diào)用:
- 只提供必須的參數(shù):
ask_ok('Do you really want to quit?')
- 提供一個(gè)可選的參數(shù):
ask_ok('Do you really want to quit?', 2)
- 或者提供所有參數(shù):
ask_ok('OK to overwrite the file?', 2, 'Come on, only yesor no!')
This example also introduces the in
keyword. This tests whether or not a sequence contains a certain value.
這個(gè)例子也在in
關(guān)鍵字中介紹叽唱,這個(gè)用來(lái)測(cè)試一個(gè)序列中是否包含一個(gè)特定的值屈呕。
The default values are evaluated at the point of function definition in the defining scope, so that
這個(gè)默認(rèn)值在函數(shù)定義的范圍內(nèi)有效,所以
i = 5
def f(arg=i):
print(arg)
i = 6
f()
will print 5
.
將會(huì)打印 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:
重點(diǎn)提示: 默認(rèn)值只會(huì)被計(jì)算一次棺亭。當(dāng)這個(gè)默認(rèn)值是類似列表虎眨,字典或者大部分類的實(shí)例這些容易變化的對(duì)象時(shí),就會(huì)有點(diǎn)不同镶摘。例如嗽桩,下面的函數(shù)會(huì)在后面的調(diào)用中積累參數(shù)。
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
This will print
這個(gè)將會(huì)打印
[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:
如果你不行這個(gè)默認(rèn)值在隨后的調(diào)用中分享钉稍,你可以把函數(shù)寫成下面這個(gè)來(lái)代替:
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
4.7.2. Keyword Arguments 關(guān)鍵字參數(shù)
Functions can also be called using keyword arguments of the form kwarg=value
. For instance, the following function:
函數(shù)也可以用kwarg=value
這樣形式的關(guān)鍵字參數(shù)來(lái)調(diào)用涤躲。例如,下面的函數(shù):
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:
接收一個(gè)必選的參數(shù)(voltage
)和三個(gè)可選的參數(shù)(state
, action
, and type
). 這個(gè)函數(shù)可以用下面的任一方式來(lái)調(diào)用:
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:
但是下面所有的調(diào)用將會(huì)是非法的:
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:
在函數(shù)調(diào)用中贡未,關(guān)鍵字參數(shù)必須遵循位置參數(shù)种樱。所有的關(guān)鍵字參數(shù)傳遞必須匹配函數(shù)接收的某個(gè)參數(shù)(例如 actor
在parrot
函數(shù)中就是一個(gè)非法的參數(shù)),并且他們的順序是不重要的俊卤。這個(gè)也包括非可選參數(shù)(例如parrot(voltage=1000)
也是合法的)嫩挤。沒(méi)有參數(shù)可以接收超過(guò)一次的值,這里有個(gè)例子就是因?yàn)檫@個(gè)限制而失敗的:
>>> def function(a):
... pass
...
>>> function(0, a=0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: function() got multiple values for keyword argument 'a'
When a final formal parameter of the form **name
is present, it receives a dictionary (see Mapping Types — dict) containing all keyword arguments except for those corresponding to a formal parameter. This may be combined with a formal parameter of the form *name
(described in the next subsection) which receives a tuple containing the positional arguments beyond the formal parameter list. (*name
must occur before **name
.) For example, if we define a function like this:
當(dāng)形參是以**name
的形式出現(xiàn)時(shí)消恍,它接收一個(gè)字典(具體看 Mapping Types — dict Map類型--字典)岂昭,包含所有的除了與其他形參相關(guān)聯(lián)的關(guān)鍵字參數(shù)。這可以跟*name
形式的形參結(jié)合起來(lái)(會(huì)在下一節(jié)討論),它接收包含形參列表之外的位置參數(shù)的元組狠怨。(*name
必須出現(xiàn)在**name
之前)约啊。例如,如果我們定義一個(gè)這樣的函數(shù):
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:
它可以這樣被調(diào)用:
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:
當(dāng)然這樣就會(huì)打印:
-- 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.
注意到打印的關(guān)鍵字參數(shù)的順序保證了它們?cè)诤瘮?shù)調(diào)用中的順序佣赖。
4.7.3. Arbitrary Argument Lists[] 隨意參數(shù)列表
(https://docs.python.org/3/tutorial/controlflow.html#arbitrary-argument-lists "Permalink to this headline")
Finally, the least frequently used option is to specify that a function can be called with an arbitrary number of arguments. These arguments will be wrapped up in a tuple (see Tuples and Sequences). Before the variable number of arguments, zero or more normal arguments may occur.
最后恰矩,最不常用的選項(xiàng)就是調(diào)用一個(gè)任意數(shù)量參數(shù)的函數(shù)。這些參數(shù)會(huì)被包含在一個(gè)元組(請(qǐng)看Tuples and Sequences 元組和序列)憎蛤。在可變數(shù)量的參數(shù)之前外傅,0個(gè)或者更多正常的參數(shù)都可能出現(xiàn)。
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.
正常情況下俩檬,那些可變參數(shù)會(huì)在形參列表的最后萎胰,因?yàn)樗麄兂薪恿藗鹘o函數(shù)的剩下的輸入?yún)?shù)。出現(xiàn)在*args
后面的任何形參都只能是關(guān)鍵子參數(shù)棚辽,這也意味著他們只能夠被用作關(guān)鍵字參數(shù)技竟,而不是位置參數(shù)。
>>> def concat(*args, sep="/"):
... return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'
4.7.4. Unpacking Argument Lists[] 參數(shù)列表的拆分 (https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists "Permalink to this headline")
The reverse situation occurs when the arguments are already in a list or tuple but need to be unpacked for a function call requiring separate positional arguments. For instance, the built-in range()
function expects separate start and stop arguments. If they are not available separately, write the function call with the *
-operator to unpack the arguments out of a list or tuple:
相反的是當(dāng)參數(shù)已經(jīng)是一個(gè)列表或元組晚胡,卻需要為要求獨(dú)立位置參數(shù)的函數(shù)調(diào)用把參數(shù)拆分開(kāi)灵奖。例如嚼沿, 內(nèi)置函數(shù)range()
期待分離的開(kāi)始和末尾參數(shù)。如果他們不能分別單獨(dú)獲取瓷患,可以用*
操作符來(lái)寫函數(shù)調(diào)用骡尽,將參數(shù)從列表或元組中拆分出來(lái)。
>>> 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:
同樣的方法擅编,字典可以用**
傳遞關(guān)鍵字參數(shù):
>>> def parrot(voltage, state='a stiff', action='voom'):
... print("-- This parrot wouldn't", action, end=' ')
... print("if you put", voltage, "volts through it.", end=' ')
... print("E's", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !
4.7.5. Lambda Expressions[] Lambda 表達(dá)式
(https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions "Permalink to this headline")
Small anonymous functions can be created with the lambda
keyword. This function returns the sum of its two arguments: lambda a, b: a+b
. Lambda functions can be used wherever function objects are required. They are syntactically restricted to a single expression. Semantically, they are just syntactic sugar for a normal function definition. Like nested function definitions, lambda functions can reference variables from the containing scope:
小的匿名函數(shù)可以通過(guò)lambda
關(guān)鍵字創(chuàng)建攀细。函數(shù) lambda a, b: a+b
返回兩個(gè)參數(shù)的和。Lambda函數(shù)可以用在任何要求函數(shù)對(duì)象的地方爱态。由于語(yǔ)法限制谭贪,他們只能有一個(gè)單獨(dú)的表達(dá)式。語(yǔ)義上講锦担,它們只是普通函數(shù)定義中的一個(gè)語(yǔ)法技巧俭识。類似嵌套函數(shù)的定義,Lambda函數(shù)可以從包含范圍內(nèi)引用變量洞渔。
>>> 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:
上面的例子用一個(gè)Lambda表達(dá)式來(lái)返回一個(gè)函數(shù)套媚。另一個(gè)用法是傳遞一個(gè)小函數(shù)作為參數(shù):
>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
4.7.6. Documentation Strings[] 文檔字符串(https://docs.python.org/3/tutorial/controlflow.html#documentation-strings "Permalink to this headline")
Here are some conventions about the content and formatting of documentation strings.
這里有一些關(guān)于文檔字符串的內(nèi)容和格式的規(guī)則。
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.
第一行應(yīng)該是關(guān)于對(duì)象用途的簡(jiǎn)介磁椒。簡(jiǎn)短起見(jiàn)堤瘤,不需要明確的陳述對(duì)象名或類型,因?yàn)檫@些可以從其他方面了解到浆熔。(除非這個(gè)名稱剛好就是描述函數(shù)操作的動(dòng)詞)這一行應(yīng)該以大寫字母開(kāi)頭本辐,以句號(hào)結(jié)尾。
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.
如果在文檔字符串中有多行医增,第二行應(yīng)該是空行慎皱,與下面的描述明確區(qū)分開(kāi)。接下來(lái)的文檔應(yīng)該有一個(gè)或多個(gè)段落來(lái)描述對(duì)象調(diào)用的約定和副作用等叶骨。
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解析器不會(huì)從多行的文檔字符串中去掉縮進(jìn)宝冕,所以如果需要的話,處理文檔的工具可以去掉多余的空行邓萨。這是使用下面的約定來(lái)完成的。文檔字符串中第一行后面的第一個(gè)非空行決定了整個(gè)文檔字符串的縮進(jìn)個(gè)數(shù)菊卷。(我們不能使用第一行缔恳,因?yàn)樗ǔJ青徑址鹗嫉囊?hào),所以它的縮進(jìn)在字符串文字中不明顯)空白相當(dāng)于脫離了所有行的字符串的開(kāi)始的縮進(jìn)洁闰∏干酰縮進(jìn)的行不應(yīng)該出現(xiàn),但是如果它們出現(xiàn)扑眉,則應(yīng)該剝離它們的所有前導(dǎo)空格纸泄。應(yīng)該測(cè)試tab鍵和空格鍵的等效性(正常一個(gè)tab等于8個(gè)空格)赖钞。
Here is an example of a multi-line docstring:
這里有個(gè)多行文檔字符串的例子:
>>> def my_function():
... """Do nothing, but document it.
...
... No, really, it doesn't do anything.
... """
... pass
...
>>> print(my_function.__doc__)
Do nothing, but document it.
No, really, it doesn't do anything.
4.7.7. Function Annotations[]
函數(shù)注解 (https://docs.python.org/3/tutorial/controlflow.html#function-annotations "Permalink to this headline")
Function annotations are completely optional metadata information about the types used by user-defined functions (see PEP 3107 and PEP 484 for more information).
函數(shù)注解是關(guān)于用戶自定義函數(shù)使用的類型的完全可選元數(shù)據(jù)信息。(詳細(xì)請(qǐng)查看 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:
注解以字典的形式保存在函數(shù)的__annotations__
屬性中聘裁,對(duì)函數(shù)其他部分沒(méi)有影響雪营。參數(shù)注解是在參數(shù)名后的冒號(hào)定義,緊跟著一個(gè)表達(dá)式衡便,用來(lái)評(píng)估注解的值献起。返回值注解是由一個(gè)文本字符 ->
定義,后面跟隨一個(gè)表達(dá)式镣陕,處于參數(shù)列表和表示def
語(yǔ)句結(jié)束的冒號(hào)之間.下面的例如有位置參數(shù)谴餐,關(guān)鍵字參數(shù)和返回值注解:
>>> def f(ham: str, eggs: str = 'eggs') -> str:
... print("Annotations:", f.__annotations__)
... print("Arguments:", ham, eggs)
... return ham + ' and ' + eggs
...
>>> f('spam')
Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
Arguments: spam eggs
'spam and eggs'
4.8. Intermezzo: Coding Style[]
間奏曲:編碼風(fēng)格 (https://docs.python.org/3/tutorial/controlflow.html#intermezzo-coding-style "Permalink to this headline")
Now that you are about to write longer, more complex pieces of Python, it is a good time to talk about coding style. Most languages can be written (or more concise, formatted) in different styles; some are more readable than others. Making it easy for others to read your code is always a good idea, and adopting a nice coding style helps tremendously for that.
現(xiàn)在你即將要寫更長(zhǎng)更復(fù)雜塊的Python代碼了,這是個(gè)談?wù)摼幋a風(fēng)格的好時(shí)機(jī)呆抑。大部分編程可以寫成不同風(fēng)格(或更簡(jiǎn)潔的說(shuō)岂嗓,格式化)。其中有一些相對(duì)而言更具有可讀性鹊碍。讓其他人更容易讀懂你的代碼總是極好的厌殉,而且采用好的編碼風(fēng)格對(duì)此有極大幫助。
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:
對(duì)于Python而言妹萨,PEP8 是作為大部分項(xiàng)目采用的風(fēng)格指導(dǎo)年枕。它推動(dòng)了非常具有可讀性且賞心悅目的編碼風(fēng)格。某種程度而言乎完,每一個(gè)Python開(kāi)發(fā)者都應(yīng)該讀一讀它熏兄。這里為你提取了最重要的幾點(diǎn):
-
Use 4-space indentation, and no tabs.
使用4個(gè)空格的縮進(jìn),而不是tabs树姨。4 spaces are a good compromise between small indentation (allows greater nesting depth) and large indentation (easier to read). Tabs introduce confusion, and are best left out.
4 個(gè)空格是在小的縮進(jìn)(允許更大的嵌套深度)和大縮進(jìn)之間一個(gè)好的妥協(xié)摩桶。Tabs則會(huì)導(dǎo)致混亂,最好將其省略帽揪。 -
Wrap lines so that they don’t exceed 79 characters.
換行硝清,所有它們不會(huì)超過(guò)79個(gè)字符This helps users with small displays and makes it possible to have several code files side-by-side on larger displays.
這個(gè)可以幫助用戶使用小的屏幕展示,并且可以在大屏幕中多個(gè)代碼文件并排展示转晰。 Use blank lines to separate functions and classes, and larger blocks of code inside functions.
使用空行來(lái)隔離開(kāi)函數(shù)和類芦拿,以及函數(shù)里較大的代碼塊。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)
.
在操作符周圍和逗號(hào)后面使用空格蔗崎, 但在括號(hào)里面不需要:a = f(1,2) + g(3,4)
Name your classes and functions consistently; the convention is to use
CamelCase
for classes andlower_case_with_underscores
for functions and methods. Always useself
as the name for the first method argument (see A First Look at Classes for more on classes and methods).
用統(tǒng)一的規(guī)則來(lái)命名類和函數(shù)。一般的慣例是扰藕,類名使用駝峰命名缓苛,函數(shù)和方法使用小寫字母和下劃線〉松睿總是使用self
作為第一個(gè)方法參數(shù)的命名未桥。(更高關(guān)于類和方法請(qǐng)查看:A First Look at Classes for more on classes and methods)Don’t use fancy encodings if your code is meant to be used in international environments. Python’s default, UTF-8, or even plain ASCII work best in any case.
如果你的代碼要在國(guó)際環(huán)境中使用笔刹,請(qǐng)不要使用花俏的編碼格式。Python默認(rèn)的是UTF8冬耿,即使是空白的ASCII在任何時(shí)候也是最好的舌菜。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.
同樣,只要其他不同語(yǔ)言的人有任何機(jī)會(huì)來(lái)閱讀或保存你的代碼淆党,那么不要使用非ASCII字符作為標(biāo)識(shí)符酷师。
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). |