当我们使用Python编程时,经常会用到函数来实现一些特定的功能。Python可以使用def关键字定义一个函数,并指定函数名和参数列表,函数体则是用来实现具体功能的部分。通过调用函数,我们可以重复使用这段代码,提高代码的复用性和可维护性。
一、定义函数
定义函数使用关键字 def,后跟函数名与括号内的形参列表。函数语句从下一行开始,并且必须缩进。下列代码创建一个可以输出限定数值内的斐波那契数列函数:
>>>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
函数定义在当前符号表中把函数名与函数对象关联在一起。解释器把函数名指向的对象作为用户自定义函数。还可以使用其他名称指向同一个函数对象,并访问访该函数:
>>>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 是由对象的类型定义的方法名称。 不同的类型定义了不同的方法。 不同的类型的方法可以使用相同的名称而不会产生歧义。 (使用 类 可以定义自己的对象类型和方法,参见 类。) 在示例中显示的方法 append() 是由列表对象定义的;它会在列表的末尾添加一个新元素。 在本例中它等同于 result = result + [a],但效率更高。
二、默认值参数
为参数指定默认值是非常有用的方式。调用函数时,可以使用比定义时更少的参数,例如:
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 ,用于确认序列中是否包含某个值。
默认值在 定义 作用域里的函数定义中求值,所以:
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
三、关键字参数
函数也可以使用 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)和三个可选参数(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
四、返回值
Python 函数使用 return 语句返回函数值,可以将函数作为一个值赋值给指定变量:
def return_sum(x,y): c = x + y return c res = return_sum(4,5) print(res)
也可以让函数返回空值:
def empty_return(x,y): c = x + y return res = empty_return(4,5) print(res)
五、可变参数列表
最后,一个较不常用的功能是可以让函数调用可变个数的参数。这些参数被包装进一个元组(查看元组和序列)。在这些可变个数的参数之前,可以有零到多个普通的参数:
def arithmetic_mean(*args): if len(args) == 0: return 0 else: sum = 0 for x in args: sum += x return sum/len(args) print(arithmetic_mean(45,32,89,78)) print(arithmetic_mean(8989.8,78787.78,3453,78778.73)) print(arithmetic_mean(45,32)) print(arithmetic_mean(45)) print(arithmetic_mean())
以上实例输出结果为:
61.0 42502.3275 38.5 45.0 0