... while a < n: ... print a,
... a, b = b, a+b ...
>>> # 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 引入了一个函数 定义 。在其后必须跟有函数名和包括形式参数的圆括号。函数体语句从下一行开始,必须是缩进的。
函数体的第一行语句可以是可选的字符串文本,这个字符串是函数的文档字符串,或者称为 docstring 。(更多关于 docstrings 的信息请参考 文档字符串 ) 有些工具通过 docstrings 自动生成在线的或可打印的文档,或者让用户通过代码交互浏览;在你的代码中包含 docstrings 是一个好的实践,让它成为习惯吧。 函数 调用 会为函数局部变量生成一个新的符号表。确切地说,所有函数中的变量赋值都是将值存储在局部符号表。变量引用首先在局部符号表中查找,然后是包含函数的局部符号表,然后是全局符号表,最后是内置名字表。因此,全局变量不能在函数中直接赋值 (除非用 global 语句命名),尽管他们可以被引用。 函数引用的实际参数在函数调用时引入局部符号表,因此,实参总是 传值调用 (这里的 值 总是一个对象引用,而不是该对象的值)。[1] 一个函数被另一个函数调用时,一个新的局部符号表在调用过程中被创建。
一个函数定义会在当前符号表内引入函数名。函数名指代的值(即函数体)存在一个被 Python 解释器认定为 用户自定义函数 的类型。这个值可以赋予其他的名字(即变量名),然后它也可以被当做函数使用。这可以作为通用的重命名机制: >>> fib
0 1 1 2 3 5 8 13 21 34 55 89
如果你使用过其他语言,你可能会反对说:fib 不是一个函数,而是一个方法,因为它并不返回任何值。事实上,没有 return 语句的函数确实会返回一个值,虽然是一个相当令人厌烦的值(指 None )。这个值被称为 None (这是一个内建名称)。如果 None 值是唯一被书写的值,那么在写的时候通常会被解释器忽略(即不输出任何内容)。如果你确实想看到这个值的输出内容,请使用 print: >>> fib(0)
>>> print fib(0) None
以下示例演示了如何从函数中返回一个包含菲波那契数列的数值链表,而不是打印它:
>>> def fib2(n): # return Fibonacci series up to n
... \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(b) 称为链表对象 result 的一个 方法 (method)。
方法是一个―属于‖某个对象的函数,它被命名为 obj.methodename,这里的 obj 是某个对象(可能是一个表达式),methodename 是某个在该对象类型定义中的方法的命名。不同的类型定义不同的方法。不同类型可能有同样名字的方法,但不会混淆(当你定义自己的对象类型和方法时,可能会出现这种情况,class 的定义方法详见 类 )。示例中演示的 append() 方法由链表对象定义,它向链表中加入一个新元素。在示例中它等同于 result = result + [b] ,不过效率更高。
4.7. 深入 Python 函数定义
在 Python 中,你也可以定义包含若干参数的函数。这里有三种可用的形式,也可以混合使用。
4.7.1. 默认参数值
最常用的一种形式是为一个或多个参数指定默认值。这会创建一个可以使用比定义时允许的参数更少的参数调用的函数,例如:
def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
while True:
ok = raw_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 IOError('refusenik user') print complaint
这个函数可以通过几种不同的方式调用:
?
只给出必要的参数:
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 关键字。它测定序列中是否包含某个确定的值。 默认值在函数 定义 作用域被解析,如下所示: 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. 关键字参数
函数可以通过 关键字参数 的形式来调用,形如 keyword = value。例如,以下的函数:
def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print \, action,
print \, voltage, \ print \, type print \, state, \
接受一个必选参数( 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 不过以下几种调用是无效的:
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 \, line 1, in ?
TypeError: function() got multiple values for keyword argument 'a'
引入一个形如 **name 的参数时,它接收一个字典(参见 Mapping Types — dict ),该字典包含了所有未出现在形式参数列表中的关键字参数。这里可能还会组合使用一个形如 *name (下一小节详细介绍)的形式参数,它接收一个元组(下一节中会详细介绍),包含了所有没有出现在形式参数列表中的参数值。( *name 必须在 **name 之前出现)例如,我们这样定义一个函数:
def cheeseshop(kind, *arguments, **keywords): print \, kind, \
print \, kind for arg in arguments: print arg