15-0-装饰器进阶及递归
一. 带参数的装饰器
我们看,装饰器其实就是一个闭包函数,再说简单点就是两层的函数。那么是函数,就应该具有函数传参功能。
login_status = {
'username': None,
'status': False,
}
def auth(func):
def inner(*args,**kwargs):
if login_status['status']:
ret = func()
return ret
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
if username == '太白' and password == '123':
login_status['status'] = True
ret = func()
return ret
return inner
你看我上面的装饰器,不要打开,他可以不可在套一层:
def auth(x):
def auth2(func):
def inner(*args,**kwargs):
if login_status['status']:
ret = func()
return ret
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
if username == '太白' and password == '123':
login_status['status'] = True
ret = func()
return ret
return inner
return auth
举例说明:抖音:绑定的是微信账号密码。 皮皮虾:绑定的是qq的账号密码。 你现在要完成的就是你的装饰器要分情况去判断账号和密码,不同的函数用的账号和密码来源不同。 但是你之前写的装饰器只能接受一个参数就是函数名,所以你写一个可以接受参数的装饰器。
def auth2(func):
def inner(*args, **kwargs):
if login_status['status']:
ret = func()
return ret
if 微信:
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
if username == '太白' and password == '123':
login_status['status'] = True
ret = func()
return ret
elif 'qq':
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
if username == '太白' and password == '123':
login_status['status'] = True
ret = func()
return ret
return inner
@auth2
def jitter():
print('记录美好生活')
@auth2
def pipefish():
print('期待你的内涵神评论')
解决方式:
def auth(x):
def auth2(func):
def inner(*args, **kwargs):
if login_status['status']:
ret = func()
return ret
if x == 'wechat':
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
if username == '太白' and password == '123':
login_status['status'] = True
ret = func()
return ret
elif x == 'qq':
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
if username == '太白' and password == '123':
login_status['status'] = True
ret = func()
return ret
return inner
return auth2
@auth('wechat')
def jitter():
print('记录美好生活')
@auth('qq')
def pipefish():
print('期待你的内涵神评论')
@auth('wechat') :分两步:
**第一步先执行auth('wechat')函数,得到返回值auth2**
**第二步@与auth2结合,形成装饰器@auth2 然后在依次执行。**
这样就是带参数的装饰器,参数可以传入多个,一般带参数的装饰器在以后的工作中都是给你提供的, 你会用就行,但是自己也一定要会写,面试经常会遇到。
二.装饰器装饰多个函数
我们现在知道标准装饰器和带参数的装饰器,我们来看看多个装饰器装饰一个函数:
def wrapper1(func):
def inner1(*args,**kwargs):
print("这是装饰器一开始")
func(*args,**kwargs)
print("这是装饰器一结束")
return inner1
def wrapper2(func):
def inner2(*args,**kwargs):
print("这是装饰器二开始")
func(*args,**kwargs)
print("这是装饰器二结束")
return inner2
def wrapper3(func):
def inner3(*args,**kwargs):
print("这是装饰器三开始")
func(*args,**kwargs)
print("这是装饰器三结束")
return inner3
@wrapper1
@wrapper2
@wrapper3
def func():
print("这是被装饰的函数")
func()
大家来推断一下,这个的打印结果
这是装饰器一开始
这是装饰器二开始
这是装饰器三开始
这是被装饰的函数
这是装饰器三结束
这是装饰器二结束
这是装饰器一结束
这个结果和我们想象的是不是不一样啊,这是为什么呢?
是因为@语法糖要检测下面的代码是不是函数,只有@语法糖检测到函数的时候才会进行执行,也就是被装饰的函数正上方的@语法糖先执行,然后在执行被装饰的函数上面的第二个装饰器,以此类推!
三.递归
什么是递归,我们通过名字先来分析一波,递类似于传递,我给你个东西你们一直向下传递,归就是将我给你们传递过去的东西,你们在传到我的手上.这是我们生活上递归
程序中的递归有点不太一样,程序中的递归就是不断调用自己本身
我们说到了调用,你们能想到什么??函数对吧,递归就是用函数实现的,我们来写一个递归
def func():
print(1)
func()
func()
这个就是递归,你们肯定有人在写函数的时候碰到过这个问题,现在和大家说一下它为什么会报错,是因为这样一直执行下去的话就是一个死循环了,Python这个语言当初设定递归的时候就不是让大家这么用的,Python中使用递归要满足两个条件才是有意义的递归
- 不断的调用自己本身
- 有明确的终止条件
我们用一个例子来说一下递归,你们问我alex多大,我不告诉你alex多大,但是alex比wusir大2岁,你们问我wusir多大,我不告诉,但是wusir比我大两岁,你们我多大,我今年18岁.你们现在知道alex多大吗?我们就可以画个表来推算alex多大.
1 | alex | 18+2+2 |
---|---|---|
2 | wusir | 18+2 |
3 | baoyuan | 18 |
Alex22岁是咱们人计算的,用程序怎么来计算呢?
def age(n):
if n == 1:
return 18
else:
return age(n-1)+2
print(age(3))
我们想知道alex多大,一共问了三次,age(3)就是咱们询问的次数,if n==1 这是一个结束条件,是因为最后一次我告诉你们我多大了,知道我多大了就需要计算wusir多大,知道wusir多大就需要计算alex多大.在问的时候就是递一共递了3次,知道我18岁的时候要就wusir和alex多大的时候就是归.
到现在为止你们还是不太明白这个是怎么实现的,我们来对递归进行一个拆解
def age1(n):
if n == 1:
return 18
else:
return age2(n-1)+2
def age2(n):
if n == 1:
return 18
else:
return age3(n - 1) + 2
def age3(n):
if n == 1:
return 18
print(age1(3))
看着还是很迷糊,莫慌看以上代码的执行流程图:
图中红色箭头是递的过程,蓝色箭头是归的过程
这个你们大家自己敲一下,体会体会
递归什么时候使用呢?我们之前做了一道题,
li = [1, 3, 4, "alex", [3, 7, 8, "TaiBai"], 5, "RiTiAn"]
这个还有印象吗,我们稍微改改需求
li = [1, 3, 4, "alex", [3, 7, 8, "TaiBai"], 5, "RiTiAn",[4,5,6,[7,[11,12,34,5],10,8,9]]]
将以上列表中的每个元素打印出来,我们之前比较少使用的for实现,使用for它有点不兼容,我们现在使用递归实现一下
def func(lst):
for i in lst:
if type(i) == list:
func(i)
else:
print(i)
func(li)
li = [1, 3, 4, "alex", [3, 7, 8, "TaiBai"], 5, "RiTiAn",[4,5,6,[7,[11,12,34,["alex","wusir","baoyuan"],5],10,8,9]]]
我们将结构修改成这样的,用刚刚写的代码也能实现.