4.6. Defining Functions
We can create a function that writes the Fibonacci series to an arbitrary boundary:
我们创建一个斐波那契数列的函数:
>>> def fib(n): # write Fibonacci series up to n ... """Print a Fibonacci series up to n.""" ... a, b = 0, 1 ... while a < n: ... print(a, end=‘ ‘) ... a, b = b, a+b ... print() ... >>> # Now call the function we just defined: ... fib(2000) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
The keyword def introduces a function definition. It must be followed by the function name and the parenthesized list of formal parameters. The statements that form the body of the function start at the next line, and must be indented.
关键词def用来定义函数。后面是函数名称,括号中列出参数,并以冒号结束函数头。函数体必须另起一行,并必须缩进:
The first statement of the function body can optionally be a string literal; this string literal is the function’s documentation string, or docstring. (More about docstrings can be found in the section Documentation Strings.) There are tools which use docstrings to automatically produce online or printed documentation, or to let the user interactively browse through code; it’s good practice to include docstrings in code that you write, so make a habit of it.
函数体的一条语句是一条字符串常量;这个字符串常量是函数文档注释(更多介绍文档字符串的请查阅 Documentation Strings)。它的作用相当于C++中的函数注释,但它可以同用户使用代码交互,可以在线咨询。因此在自己的代码中包含文档注释是非常好的习惯。
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.
执行函数时,函数会创建一个符号表用来存储该函数中使用的本地变量。更准确的说,所有在函数中变量的值存储在符号表中;因此,变量引用首先在本地符号表中查找,然后在函数创建的符号表,然后是全局符号表,最后是内置的变量名。因此全局变量不能直接在函数体中赋值((因为全局变量不会去查找函数创建的符号表,因此它会认为没有该符号变量)除非使用global语句)。
The actual parameters (arguments) to a function call are introduced in the local symbol table of the called function when it is called; thus, arguments are passed using call by value (where the value is always an object reference, not the value of the object). [1] When a function calls another function, a new local symbol table is created for that call.
当一个函数被调用时,实参也会被导入到该函数所创建的符号表中。因此,参数是引用传递而不是值传递。当一个函数调用另一个函数时,该函数会为这次调用创建一个新的符号表。
A function definition introduces the function name in the current symbol table. The value of the function name has a type that is recognized by the interpreter as a user-defined function. This value can be assigned to another name which can then also be used as a function. This serves as a general renaming mechanism:
当一个函数调用另一个函数时,会把这个被调用的函数的名字添加到当前的符号表中。函数名字的值也是一个类型,这个类型能被解释器识别出这是一个用户定义的函数。函数名对应的值也能赋给另一个变量。这个变量就相当于C++中的函数指针:
>>> fib <function fib at 10042ed0> >>> f = fib >>> f(100) 0 1 1 2 3 5 8 13 21 34 55 89
Coming from other languages, you might object that fib is not a function but a procedure since it doesn’t return a value. In fact, even functions without a return statement do return a value, albeit a rather boring one. This value is called None (it’s a built-in name). Writing the value None is normally suppressed by the interpreter if it would be the only value written. You can see it if you really want to using print():
来自其他语言的认识,你可能觉得fib不是一个函数而是一个执行程序,因为它没有返回值,实际上,它有一个返回值为None(一个内置名称)。你可以使用print()看到:
>>> fib(0) >>> print(fib(0)) None
It is simple to write a function that returns a list of the numbers of the Fibonacci series, instead of printing it:
写一个简单的函数返回斐波那契数列的列表很容易:
>>> def fib2(n): # return Fibonacci series up to n ... """Return a list containing the Fibonacci series up to n.""" ... result = [] ... a, b = 0, 1 ... while a < n: ... result.append(a) # see below ... a, b = b, a+b ... return result ... >>> f100 = fib2(100) # call it >>> f100 # write the result [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
4.7. More on Defining Functions
It is also possible to define functions with a variable number of arguments. There are three forms, which can be combined.
我们可以定义多种函数参数形式,有一下三种形式:
4.7.1. Default Argument Values
The most useful form is to specify a default value for one or more arguments. This creates a function that can be called with fewer arguments than it is defined to allow. For example:
给参数指定默认值非常有用。这样允许函数调用使用默认的值,例如:
def ask_ok(prompt, retries=4, complaint=‘Yes or no, please!‘): 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 OSError(‘uncooperative user‘) print(complaint)
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 yes or no!‘)
函数可以有以下几个调用形式:
只给一个参数: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!‘)
This example also introduces the in keyword. This tests whether or not a sequence contains a certain value.
这个例子也介绍了关键字in。用来测试这个序列是否包含某个确切的值。
The default values are evaluated at the point of function definition in the defining scope, so that
i = 5 def f(arg=i): print(arg) i = 6 f()
将会打印5.
4.7.2. Keyword Arguments
Functions can also be called using keyword arguments of the form kwarg=value. For instance, the following function:
函数可以使用关键字参数,例如下面的函数:
def parrot(voltage, state=‘a stiff‘, action=‘voom‘, type=‘Norwegian Blue‘): print("-- This parrot wouldn‘t", action, end=‘ ‘) print("if you put", voltage, "volts through it.") print("-- Lovely plumage, the", type) print("-- It‘s", state, "!")
accepts one required argument (voltage) and three optional arguments (state, action, and type). This function can be called in any of the following ways:
接收一个必须输入的参数(voltage)和三个可选参数(state,action 和 type),这个函数有一下几种调用方式:
parrot(1000) # 1 positional argument parrot(voltage=1000) # 1 keyword argument parrot(voltage=1000000, action=‘VOOOOOM‘) # 2 keyword arguments parrot(action=‘VOOOOOM‘, voltage=1000000) # 2 keyword arguments parrot(‘a million‘, ‘bereft of life‘, ‘jump‘) # 3 positional arguments parrot(‘a thousand‘, state=‘pushing up the daisies‘) # 1 positional, 1 keyword
but all the following calls would be invalid:
但是下面的调用方式不合法:
parrot() # required argument missing parrot(voltage=5.0, ‘dead‘) # non-keyword argument after a keyword argument parrot(110, voltage=220) # duplicate value for the same argument parrot(actor=‘John Cleese‘) # unknown keyword argument
In a function call, keyword arguments must follow positional arguments. All the keyword arguments passed must match one of the arguments accepted by the function (e.g. actor is not a valid argument for the parrot function), and their order is not important. This also includes non-optional arguments (e.g. parrot(voltage=1000) is valid too). No argument may receive a value more than once. Here’s an example that fails due to this restriction:
在函数调用中,关键字参数后面必须是关键字参数。所有的关键字参数传递必须匹配其中一个函数可接受的参数,他们的顺序不重要。
When a final formal parameter of the form **name is present, it receives a dictionary (see Mapping Types — dict) containing all keyword arguments except for those corresponding to a formal parameter. This may be combined with a formal parameter of the form *name (described in the next subsection) which receives a tuple containing the positional arguments beyond the formal parameter list. (*name must occur before **name.) For example, if we define a function like this:
当最后一个参数形式是**name。它表示是一个字典类型。*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) keys = sorted(keywords.keys()) for kw in keys: print(kw, ":", keywords[kw])
It could be called like this:
可以这样调用:
cheeseshop("Limburger", "It‘s very runny, sir.", "It‘s really very, VERY runny, sir.", shopkeeper="Michael Palin", client="John Cleese", sketch="Cheese Shop Sketch")
and of course it would print:
打印结果如下:
-- Do you have any Limburger ? -- I‘m sorry, we‘re all out of Limburger It‘s very runny, sir. It‘s really very, VERY runny, sir. ---------------------------------------- client : John Cleese shopkeeper : Michael Palin sketch : Cheese Shop Sketch
Note that the list of keyword argument names is created by sorting the result of the keywords dictionary’s keys() method before printing its contents; if this is not done, the order in which the arguments are printed is undefined.
注意,关键字名字的列表的顺序是关键字字典调用keys()之后的排序结果。如果不排序,那么打印出来是定义的。
4.7.3. Arbitrary Argument Lists
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.
最后,最不经常用的一种函数包括任意数量的参数。这些参数被封装在一个元组中。在任意多个参数前可以有0或多个正规参数。
def write_multiple_items(file, separator, *args): file.write(separator.join(args))
Normally, these variadic arguments will be last in the list of formal parameters, because they scoop up all remaining input arguments that are passed to the function. Any formal parameters which occur after the *args parameter are ‘keyword-only’ arguments, meaning that they can only be used as keywords rather than positional arguments.
一般地,这些参数都必须在正常参数之后,任何正常参数出现在*args后面都属于关键字参数,这意味着他们不能作为正规参数使用。
>>> def concat(*args, sep="/"): ... return sep.join(args) ... >>> concat("earth", "mars", "venus") ‘earth/mars/venus‘ >>> concat("earth", "mars", "venus", sep=".") ‘earth.mars.venus‘
4.7.4. Unpacking Argument Lists
The reverse situation occurs when the arguments are already in a list or tuple but need to be unpacked for a function call requiring separate positional arguments. For instance, the built-in range() function expects separate start and stop arguments. If they are not available separately, write the function call with the *-operator to unpack the arguments out of a list or tuple:
相反的情况,我们需要用列表或元组作为参数,但是函数需要单独的固定位置的参数,这是我们需要解包。例如,内置函数range()需要单独的start(起始位置)和stop(终止位置)两个参数。如果他们不合适分离,用*操作符解包将参数从列表或元组中提取出来:
>>> list(range(3, 6)) # normal call with separate arguments [3, 4, 5] >>> args = [3, 6] >>> list(range(*args)) # call with arguments unpacked from a list [3, 4, 5]
In the same fashion, dictionaries can deliver keyword arguments with the **-operator:
同理,字典提取关键字参数使用**操作符:
>>> def parrot(voltage, state=‘a stiff‘, action=‘voom‘): ... print("-- This parrot wouldn‘t", action, end=‘ ‘) ... print("if you put", voltage, "volts through it.", end=‘ ‘) ... print("E‘s", state, "!") ... >>> d = {"voltage": "four million", "state": "bleedin‘ demised", "action": "VOOM"} >>> parrot(**d) -- This parrot wouldn‘t VOOM if you put four million volts through it. E‘s bleedin‘ demised !
4.7.5. Lambda Expressions
Small anonymous functions can be created with the lambda keyword. This function returns the sum of its two arguments: lambda a, b: a+b. Lambda functions can be used wherever function objects are required. They are syntactically restricted to a single expression. Semantically, they are just syntactic sugar for a normal function definition. Like nested function definitions, lambda functions can reference variables from the containing scope:
短小的匿名函数可以用lambda关键字创建。这个函数返回两个参数的和:lambda a,b: a + b。lambda函数可以在任何需要函数对象的地方使用。它在语法上要求只能有单个表达式。从语义上讲,他们只是正常函数的简单包装。类似于嵌套函数定义,lambda函数可以从所包含的范围内引用变量:
>>> def make_incrementor(n): ... return lambda x: x + n ... >>> f = make_incrementor(42) >>> f(0) 42 >>> f(1) 43
The above example uses a lambda expression to return a function. Another use is to pass a small function as an argument:
上面的例子使用lambda表达式返回一个函数对象。另一个用途是将lambda表达式作为参数传递:
>>> pairs = [(1, ‘one‘), (2, ‘two‘), (3, ‘three‘), (4, ‘four‘)] >>> pairs.sort(key=lambda pair: pair[1]) >>> pairs [(4, ‘four‘), (1, ‘one‘), (3, ‘three‘), (2, ‘two‘)]
4.7.6. Documentation Strings
Here are some conventions about the content and formatting of documentation strings.
The first line should always be a short, concise summary of the object’s purpose. For brevity, it should not explicitly state the object’s name or type, since these are available by other means (except if the name happens to be a verb describing a function’s operation). This line should begin with a capital letter and end with a period.
If there are more lines in the documentation string, the second line should be blank, visually separating the summary from the rest of the description. The following lines should be one or more paragraphs describing the object’s calling conventions, its side effects, etc.
The Python parser does not strip indentation from multi-line string literals in Python, so tools that process documentation have to strip indentation if desired. This is done using the following convention. The first non-blank line after the first line of the string determines the amount of indentation for the entire documentation string. (We can’t use the first line since it is generally adjacent to the string’s opening quotes so its indentation is not apparent in the string literal.) Whitespace “equivalent” to this indentation is then stripped from the start of all lines of the string. Lines that are indented less should not occur, but if they occur all their leading whitespace should be stripped. Equivalence of whitespace should be tested after expansion of tabs (to 8 spaces, normally).
Here is an example of a multi-line docstring:
>>> def my_function(): ... """Do nothing, but document it. ... ... No, really, it doesn‘t do anything. ... """ ... pass ... >>> print(my_function.__doc__) Do nothing, but document it. No, really, it doesn‘t do anything.
4.8. Intermezzo: Coding Style
- Use 4-space indentation, and no tabs.
4 spaces are a good compromise between small indentation (allows greater nesting depth) and large indentation (easier to read). Tabs introduce confusion, and are best left out.
- 使用4个空格作为缩进。
- Wrap lines so that they don’t exceed 79 characters.
This helps users with small displays and makes it possible to have several code files side-by-side on larger displays.
- Use blank lines to separate functions and classes, and larger blocks of code inside functions.
- 使用空行分隔函数和类,以及函数内部的大代码块
- When possible, put comments on a line of their own.
- Use docstrings.
- 使用文档注释
- Use spaces around operators and after commas, but not directly inside bracketing constructs: a = f(1, 2) + g(3, 4).
- Name your classes and functions consistently; the convention is to use CamelCase for classes and lower_case_with_underscores for functions and methods. Always use self as the name for the first method argument (see 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.
- 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.