了解了定义函数的基本格式之后,对其中的某些细节进行深入分析、透彻了解,才能定义出具有强大功能的函数。
以关键词 return
发起的语句,主要作用是终止当前函数,并返回指定的对象。
>>> def foo():
... print('before return')
... return
... print('after return')
...
>>> foo()
before return
在函数 foo()
中,关键词 return
后没有写任何对象,也构成了 return 语句,其作用与 return None
等效。观察对此函数的调用结果,发现 return
之前的语句被执行,之后的没有被执行。正如前所述,return 语句终止了当前函数,其后的语句不执行。
再看它能返回的对象,理论上说可以返回任意多个任何 Python 对象,当然,具体的数量以及对象类型要视实际情况而定。
>>> def bar():
... return 1, 2, 3
...
>>> a = bar() # (4)
>>> a
(1, 2, 3)
>>> b, c, d = bar() # (5)
>>> b
1
>>> c
2
>>> d
3
这里定义的 bar()
函数返回了三个整数对象,以注释(4)的方式,变量 a
引用返回对象——自动将三个整数对象组装成元组,并通过赋值语句被变量 a
引用。注释(5)则使用三个变量,通过赋值语句依次对应引用 bar()
返回的每个整数对象。
>>> def laoqi():
... return dict(work='coder', age=30, gender='male')
...
>>> laoqi()['work'] # (6)
'coder'
函数 laoqi()
的 return
关键词后面是一个字典对象,注释(6)中 laoqi()
即调用此函数,并将字典对象返回到此位置,即得到了 {'work': 'coder', 'age': 30, 'gender': 'male'}['work']
,从而读取到键 'work'
的值 'coder'
。
高德纳(Donald Ervin Knuth)的名著《计算机程序设计艺术》(The Art of Computer Programming)被开发者奉为经典,其中记载了古老的斐波那契数列。1150年印度数学家 Gopala 首先描述了这个数列。在西方,最先研究这个数列的人是比萨的列奥那多(全名为:Leonardo Fibonacci ),他借用描述兔子生长的数目介绍了这个数列。
将此过程写成数学式,即:
根据此数学式得到的数列,如:0,1,1,2,3,5,8,13,21,\cdots ,就是斐波那契数列。接下来的任务是研究如何用 Python 编写计算斐波那契数列的函数。
此问题相对之前的函数,显然有了一点点难度,但仍然希望读者能首先独立思考并尝试,之后再参考下文中的代码。
关于斐波那契数列的函数,本书中结合不同的学习内容给出多种写法,此处暂且提供其中的一个,请参考。
#coding:utf-8
'''
filename: fibonacci.py
'''
def fibo_loop(n):
result = [0, 1]
for i in range(n-2):
result.append(result[-2] + result[-1])
return result
if __name__ == "__main__":
fib_lst = fibo_loop(10)
print(fib_lst)
程序调试结果:
% python fibonacci.py
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
函数 fibo_loop()
中用循环语句实现了斐波那契数列(读者也可以将其中的 for 循环改为 while 循环)。这种方法简单,而且直接与数学表达式对应,容易理解。除了此方法之外,更常见的或许是用“递归”的方法来实现。
def fibo_recur(n):
if n <= 1:
return n
else:
return (fibo_recur(n-1) + fibo_recur(n-2))
if __name__ == "__main__":
fib_lst = [fibo_recur(i) for i in range(10)]
print(fib_lst)
递归(recursion)是一种算法,在函数的定义中使用函数自身,如上面定义的函数 fibo_recur()
所示,在函数体内的语句中使用本函数。虽然只要讲解递归算法,必然会以斐波那契数列函数为例,但不能由此认为斐波那契数列只能用递归方法实现,也不能认为用递归方法所实现的斐波那契数列函数就是最好的——恰恰相反。更何况,Python 发明人吉多·范罗索姆更讨厌在 Python 中使用递归(http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html)。当然,对他的观点,业界也是有争论的。从学习者的角度看,以上列举的两种方法都应当理解和掌握——艺不压身,为此本书在7.5节专门介绍递归。