4.2.6 函数的返回值

函数作为一种模块构件,它与其他模块如何协作、交换信息?我们已经知道,通过函数 调用时的参数传递,可以实现从函数外部向函数内部输入数据。本节讨论函数向外部输出信 息的问题。

在数学中,函数是从定义域到值域的映射,亦即从自变量计算出函数值。编程语言中的 函数原本就是数学函数的模仿物,自然也可以计算出一个结果输出给函数调用者,我们称函 数输出的计算结果为函数的返回值(returned value)。

在前面几章中,我们已多次使用过具有返回值的内建函数和库函数。例如,内建函数 len() 能够接收一个字符串,然后返回该字符串的长度;数学库中的函数 math.sqrt()接收一个 数值,并返回该数值的平方根。我们还看到,带有返回值的函数基本上可以当作一个值来看 待,可以和其他数据一起进行运算,构成表达式。例如:

(-b + math.sqrt(b*b – 4*a*c)) / 2*a 
range(len("hello"))
x = input("Enter a number:")

如何自定义带有返回值的函数呢?Python 语言提供了一条 return 语句用于从函数返 回值,用法如下:

def f():
...
return <表达式 1>, ..., <表达式 n>
...

其语义是:当 Python 在执行函数 f()时,一旦遇到 return 语句,就终止执行函数,并将 控制返回到函数调用点,同时将各表达式的计算结果返回给调用者。

与 Python 内建函数、库函数一样,带返回值的用户自定义函数可以像一个普通的数据 值一样使用,例如用在表达式中参加运算(当然要求数据类型合法)或者作为赋值语句的右 端为变量赋值。

例如,下面的函数实现了数学函数 f(x) = x2 的功能:

>>> def sq(x):
        return x * x
>>> sq(2)
4
>>> print sq(3) + 1
10
>>> a = 4
>>> b = sq(a)
>>> print b
16

再看一个例子,下面的 dist()函数能够计算平面上两点间的距离。我们将平面上的点 表示为由横坐标和纵坐标组成的元组(x,y)。根据数学中的距离公式,并利用上面的 sq() 函数,可以写出如下代码:

>>> import math
>>> def dist(u,v):
        d = math.sqrt(sq(v[0]-u[0])+sq(v[1]-u[1])) return d
>>> dist((0,0),(4,0))
4.0
>>> dist((0,0),(0,5))
5.0
>>> dist((0,0),(1,1))
1.4142135623730951
>>> dist((1,2),(3,4))
2.8284271247461903

如果函数返回值有多个,那么调用者需要使用多个变量来接收函数的返回值。例如下面 的函数 headtail()对一个列表取出头尾元素:

>>> def headtail(list):
    return list[0], list[len(list)-1]
>>> headtail([1,2,3,4,5]) 
(1, 5)

调用 headtail 这种返回多个值的函数时,调用者可以利用多变量同时赋值语句来接

收多个返回值,也可以只用一个变量来接收返回值,因为函数返回的“多个值”实际上构成

一个元组。

>>> h,t = headtail([1,2,3,4,5])
>>> print h,t 
1 5
>>> v = headtail([1,2,3,4,5])
>>> v 
(1, 5)

函数中的 return 语句通常都出现在函数的末尾,因为函数一般都是执行完所有步骤 之后才能得出计算结果并返回。然而,有时我们希望在函数到达末尾之前就终止执行并返回, 例如当函数检测到不正确的数据时就没有必要继续执行,因为计算下去只能带来错误结果。 下面这个例子检查用户输入(要求是正数),如果不满足要求则退出函数,否则对用户数据 进行处理。代码如下:

>>> def f(x):
    if x <= 0:
        print "Positive numbers only, please." 
        return
    y = x ** 3 
    return y
>>> f(0)
Positive numbers only, please.
>>> f(2) 
8

最后要说明一点,在 Python 中,任何函数无论是否包含 return 语句,总是要返回一个值的。如果包含 return 语句,自然就返回程序员指定的值;如果不含 return 语句, 则函数总是返回一个称为 None 的特殊对象。如果编程时忘记在函数中用 return 语句返回 值,而调用处又企图使用返回值,则可能出错。例如,假设上面定义的 dist()函数忘了最 后的 return 语句,我们看会带来什么后果:

>>> import math
>>> def dist(u,v):
        d = math.sqrt(sq(v[0]-u[0])+sq(v[1]-u[1]))
>>> print dist((0,0),(2,2))
None
>>> print 2 + dist((0,0),(2,2))
Traceback (most recent call last):
File "<pyshell#42>", line 1, in <module> print 2 + dist((0,0),(2,2))
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'

可见调用 dist()后得到的结果是 None;如果将这个 None 用于表达式中(例中是与 2 相 加)则可能出错,因为对 None 对象并没有定义加法运算。对初学 Python 编程的人来说, 这是容易犯错的地方,所以一定要注意返回值。