装饰器深入 、递归函数入门
多层语法糖
def outter1(func1):
def wrapper1(*args, **kwargs):
print('前处理')
res = func1(*args, **kwargs)
print('后处理')
return res
return wrapper1
def outter2(func1):
def wrapper2(*args, **kwargs):
print('前处理')
res = func1(*args, **kwargs)
print('后处理')
return res
return wrapper2
def outter3(func1):
def wrapper3(*args, **kwargs):
print('前处理')
res = func1(*args, **kwargs)
print('后处理')
return res
return wrapper3
@outter1 # outter1(wrapper2)
@outter2 # outter2(wrapper3)
@outter3 # outter3(真正的index) ——> wrapper3
def index():
print('miku')
index()
输出结果:
推导过程
有参装饰器 (补充)
def outer_plus(mode): # 传到这里的形参
def outer(func_name):
def inner(*args, **kwargs):
print(mode) # 这里可以用传进来的参数
res = func_name(*args, **kwargs)
return res
return inner
return outer
@outer_plus('在括号里传参数')
def func():
pass
# 请注意:
# 函数名+括号的优先级最高
# 所以outer_plus()这个函数会优先执行 此时先忽略语法糖的@
# outer_plus()运行结束返回一个outer 然后语法糖再发挥功能 @outer 将func传入outer
装饰器修复技术(了解)
装饰器修复只是为了让装饰器‘装’的更像!
# 1.这是一个经典的装饰器
def outer(func_name):
def inner(*args, **kwargs):
res = func_name(*args, **kwargs)
return res
return inner
@outer
def index():
pass
# 2.通过help方法查看index到底是什么
help(index)
# 结果如下:可见通过help函数可以知道index实际是指向inner函数 ps:被识破了吗 ~
# 3.想办法骗过help函数
from functools import wraps # 首先这里导个包
def outer(func_name):
@wraps(func_name) # 在这里添加一行代码
def inner(*args, **kwargs):
res = func_name(*args, **kwargs)
return res
return inner
@outer
def index():
pass
help(index) # 大功告成! 现在help也无法识破了 装的非常像了 是一个优雅的装饰器=。=
# 运行如下: ps:装再怎么像 实际上还是在运行inner
递归函数
前戏
# 函数自己调用自己会发生什么?
# 1.直接调用
def index():
print('from index')
index()
index()
# 会报错:RecursionError: maximum recursion depth exceeded while calling a Python object
# python限制默认调用自己的次数为1000次 # 一直调用自己就强制报错 # 这也是一种保护机制
# JAVA没有这种限制 # 越晚出来的编程语言 考虑越周到 # 以后可能出来新的编程语言 吸收各种编程语言的优点
# 2.间接调用
def index():
print('from index')
func()
def func():
print('from func')
index()
func() # 你调用我 我调用你 老样子还是报错 因为调用次数太多了
# 3.看一下到底调用了多少次!
count = 0
def index():
global count
count += 1
print(count)
index()
index()
'''官网提供的最大递归深度为1000 我们在测试的时候可能会出现996 997 998'''
# 4.补充一点 修改python默认的递归深度
import sys # 导入sys模块
sys.setrecursionlimit(3000) # 修改默认的递归深度为3000次
递归函数概念
1.递归函数概念
1.直接或者间接调用自己
2.每次调用都必须比上一次简单 并且需要有一个明确的结束条件
递推:一层层往下
回溯:基于明确的结果一层层往上
"""
get_age(5) = get_age(4) + 2
get_age(4) = get_age(3) + 2
get_age(3) = get_age(2) + 2
get_age(2) = get_age(1) + 2
get_age(1) = 18
"""
def get_age(n):
if n == 1:
return 18 #
return get_age(n-1) + 2 # 这里会一直调用get_age # 函数调用的优先级比return高
res = get_age(5)
print(res)
练习
'''
1.利用递归函数依次打印列表中每一个数据值
l1 = [1,[2,[3,[4,[5,[6,[7,[8,]]]]]]]]
'''
l1 = [1, [2, [3, [4, [5, [6, [7, [8, ]]]]]]]]
# 思路
# 先不用递归函数 先想正常取值怎么把每个值都取出来 然后用递归函数实现
# a = l1.pop() # 弹出第末尾元素
# print(a) # 输出弹出的值
# print(l1[0]) # 原列表就剩下一个 1 输出它
# b = a.pop() # 弹出a末尾的值
# print(a[0]) # 输出a列表的第一个值 2
def recursion(depth_list): # 传入一个列表
if len(depth_list) == 1:
print(depth_list[0])
return
else:
list_swap = depth_list.pop()
print(depth_list[0], end=' ')
return recursion(list_swap)
recursion(l1)
'''2.有参装饰器编写多种用户登录校验策略'''
# 多种登录应该对应的是 邮箱登录 QQ登录 微信登录 手机号登录
# 模式一直接校验
# 模式二用列表存数据
userdata_list = ['jason|123', 'kevin|321', 'oscar|222']
def outer_plus(mode):
def outer(func_name):
def inner(*args, **kwargs):
while True:
if mode == '1': # 数据值写死
while True:
username = input('请输入用户名>>>')
password = input('请输入密码>>>')
if username == 'miku' and password == '123':
res = func_name(*args, **kwargs)
return res
else:
print('模式1认证失败')
elif mode == '2': # 列表存储数据的情况
while True:
username = input('请输入用户名>>>')
password = input('请输入密码>>>')
for one_user in userdata_list:
one_name, one_password = one_user.split('|')
if username == one_name and password == one_password:
res = func_name(*args, **kwargs)
return res
else:
print('模式2认证失败')
elif mode == '3': # 文件存储数据的情况
username = input('请输入用户名>>>').strip()
password = input('请输入密码>>>').strip()
with open('userinfo.txt', 'r', encoding='utf8') as f:
for line in f:
line.strip('\n')
one_name, one_password = line.split(':')
if username == one_name.strip() and password == one_password.strip(): # 有隐藏的空格
res = func_name(*args, **kwargs)
return res
else:
print('文件中没有此用户')
else:
print('=。=')
return
return inner
return outer
mode_def = input('''
1.直接验证
2.列表存数据
3.文件存数据
>>> 请输入数字:
''').strip()
@outer_plus(mode_def)
def func():
print('我是func 我执行了哈哈哈')
func()