一.闭包
- 在Python中,函数支持嵌套。
- 如果在一个内部函数中对外部函数作用域(非全局作用域)的变量进行引用,那么内部函数称为闭包。闭包满足三个条件:
1.存在于嵌套关系的函数中。
2.嵌套的内部函数引用了外部函数的变量。
3.嵌套的外部函数将内部函数名作为返回值返回。
示例:
def fun_out(n=0):
count = [n] # 外部函数内变量
def fun_inner():
count[0] += 1 # 引用外部函数的变量
return count[0]
return fun_inner # 返回内部函数名称
quote = fun_out(5)
print(quote()) # 输出6
从变量的生命周期讲,在外部函数执行结束后,变量count将被销毁。而当外部函数执行完之后,才返回内部函数名称,才会执行内部函数。由于内部函数使用了count变量,所以程序应该出现运行时错误。
但是并没有发生这样的错误。因为闭包会记得外层函数的作用域,不会释放这个变量。
- 那么闭包的作用是什么?是保存函数的状态信息,使函数的局部变量信息依然可以保存下来。就是保存局部变量不被销毁。
二.函数的递归调用
- 函数在执行的过程中直接或间接调用自己本身,称为递归调用。
示例:求1~10的平方和。
def f(x):
if x == 1:
return 1
else:
return (f(x - 1) + x * x)
print(f(10)) # 输出385
- 递归调用的执行过程分为递推过程和回归过程两部分。这两个过程由递归终止条件控制。
示例:汉诺塔问题。
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘(如下图)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
得出有这样几个限制条件:
1.大圆盘必须放在小圆盘下面。
2.在三根杆直接一次只能移动一个圆盘。
3.只能移动在最顶端的圆盘。
分析,求解过程就是:
1.有一个盘子的话,就是将盘子从A直接移动到C。
2.有两个盘子的话,将小盘子从A移动到B,大盘子从A移动到C。小盘子从B移动到C。
3.有n个盘子的话,视作将上面n-1个盘子和最下面第n个盘子的情况。将n-1个盘子从A移动到B,第n个盘子从A移动到C,n-1个盘子从B到C。问题再次转化为搬动n-1个盘子。继续上面的操作,直到变成只搬一个盘子的情况。
递归结束的时候,只移动一个盘子。
def move(source, target):
print(source, '->', target)
def hanoi(n, source, temp, target):
if n == 1:
move(source, target)
else:
hanoi(n - 1, source, target, temp) # 将n-1个盘子移动到中间杆
move(source, target) # 将最后一个盘子搬到目标杆
hanoi(n - 1, temp, source, target) # 将n-1个盘子搬到目标杆
n = int(input("输入盘子数:"))
print("步骤如下:")
hanoi(n, 'A', 'B', 'C')