递归
递归指的是函数直接或间接的调用自身。
有一则故事:
从前有座山,山里有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事的内容是:从前有座山,山里有座庙。。。。
可能图片更直观,相信都见过类似的图片吧
说明:
- 递归一定要控制递归的次数,当符合某一条件时要终止递归调用
- 几乎所有的递归都能用while循环来代替
递归的优缺点:
优点:可以把问题简单化,让思路更加清晰,代码更简洁
缺点:递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果
递归调用分为两个阶段:
递推阶段:从原问题出发,按递归公式递推,从未知到已知,最终达到递归终止条件
回归条件:按递归终止条件求出结果,逆向逐步带入递归公式,回归到原问题求解
先举个递归的栗子吧,我就喜欢举例子,文字描述总不如栗子更容易理解,也正好了解一下在什么请况下使用递归比较好吧
如老和尚讲故事:
def f():
print('从前有座山,山里有座庙,庙里有个老和尚讲故事,讲的是:')
f()
f()
结果呢:
这个就是没有加限制此数,最后崩溃掉了
再如,用递归求阶乘:
def myfac(n):
if n == 1: # 限制条件,当为 1 时终止递归
return 1
return n * myfac(n - 1)
print(myfac(5)) # 5 的阶乘 120
递推过程:
5! = 5 * 4!
5! = 5 * 4 * 3!
5! = 5 * 4 * 3 * 2!
5! = 5 * 4 * 3 * 2 * 1!
5! = 5 * 4 * 3 * 2 * 1
回归过程:
5! = 5 * 4 * 3 * 2
5! = 5 * 4 * 6
5! = 5 * 24
5! = 120
配个图:
闭包
什么是闭包:
如果一个内嵌函数访问了外部嵌套函数的变量,则这个内嵌函数就是闭包
闭包必须满足三个条件:
- 必须是一个内嵌函数
- 内嵌函数必须引用外部函数的变量
- 外部函数返回值必须是内嵌函数
举个栗子:
分析以上代码:
pow2接收的返回值是什么? —–> fn , 没错,就是fn,因为maker_power内部的 fn 是一个函数,但此时没被调用,所以return 的 fn 就是一个函数名。强调:此函数虽然没被调用,但是 y 是不会被释放的。
此时的pow2实际上就是 fn 了
pow2(5) 在这时其实就是调用fn 函数了,并把 5 传进去,即x = 5,上边说的 有 y 还没有被释放,返回x 的 y 次方,即返回5^2=25
注意:fn 是函数名 fn()才是调用 fn 函数(即,函数名加括号才是调用)
再来个温习一下:
装饰器
装饰器是一个函数,传入的是一个函数,返回的也是一个函数
例如:
def 装饰器函数名(参数):
语句块
return 函数对象
@装饰器函数名
def 函数名(形参列表):
语句块
装饰器的原理:
被装饰函数的变量(函数名)绑定装饰器函数调用后返回的函数
举几个例子:
def mydeco(fn):
def fx():
print('fx正在被调用')
return fx
def myfun():
print('myfun正在被调用')
myfun = mydeco(myfun)
myfun() # 结果:fx正在被调用 为什么不是myfun正在被调用?
先理解这个例子,
mydeco(myfun) 这句是调用mydeco函数,参数是一个函数myfun,即fn = myfun,返回fx,即接收的myfun=fx,
myfun()就是调用fx(),执行print(‘fx正在被调用’)这句话,所以打印的不是myfun正在被调用,跟他根本没有关系。
另一个写法:
def mydeco(fn):
def fx():
print('fx正在被调用')
return fx
@mydeco
def myfun():
print('myfun正在被调用')
# myfun = mydeco(myfun)
myfun()
再深入一层讲解装饰器:
先看代码:
def mydeco(fn):
def fx():
print('这是被装饰之前')
fn() # 调用被装饰函数
print('这是被装饰之后')
return fx
@mydeco
def myfun():
print('myfun正在被调用')
myfun()
myfun() 再次讲解这句话,加深理解上边的栗子
myfun实际可以写成两句话:
myfun = mydeco(myfun)
myfun()
初步可认为是调用myfun函数,但是myfun有装饰器,所以myfun会当做一个参数传入装饰器函数里,即fn = myfun,调用mydeco函数,先执行print(‘这是被装饰之前’)这就话,然后执行fn()函数,即调用myfun()函数,执行print(‘myfun正在被调用’)这句话,fn()函数执行完毕,继续执行装饰器函数,执行print(‘这是被装饰之后’)这句话,
所以最后打印结果是:
这是被装饰之前
myfun正在被调用
这是被装饰之后
装饰器应用:
def privieged_check(fn):
def fx(name, x):
print('正在进行验证...')
if True:
fn(name, x)
else:
print('权限验证失败')
return fx
def message_send(fn):
def fy(name, money):
fn(name, money)
print('正在发送短息给', name)
return fy
@message_send
@privieged_check
def savemoney(name, x):
print(name, '存钱', x, '元')
savemoney('小张', 200)
注意:如果被装饰的函数有多个装饰器,优先执行最近的
执行结果:
正在进行验证...
小张 存钱 200 元
正在发送短息给 小张
执行过程:
其实自己绕绕也就绕出来了!
愿意和大家一起交流,huamuxiong_2018@163.com
本节图有网上百度的,有助于理解,如果有侵权,还请告知,我会删除,谢谢