python学习笔记
今日内容概要
- 作业讲解
- 多层装饰器
- 有参装饰器
- 递归函数
- 算法之二分法
今日内容详细
作业讲解
1.编写一个用户认证装饰器
基本要求
执行每个函数的时候必须先校验身份 eg: jason 123
拔高练习(有点难度)
执行被装饰的函数 只要有一次认证成功 那么后续的校验都通过
函数:register login transfer withdraw
提示:全局变量 记录当前用户是否认证
is_login = {'is_login' : False,}
# 2.编写装饰器
def login_auth(func_name):
def inner(*args, **kwargs):
# 2.3判断全局字典is_login对应的值是否是True
if is_login.get('is_login'):
# 2.4直接执行被装饰函数即可
res = func_name(*args, **kwargs)
return res
# 2.1假设是第一次调用,肯定需要校验用户身份
username = input('username:').strip()
password = input('password:').strip()
if username == 'jason' and password == '123':
res = func_name(*args, **kwargs)
# 2.2保存用户登录的状态
is_login['is_login'] = True
return res
else:
print('权限不够 无法执行')
return inner
# 1.定义函数
@login_auth
def register():
print('注册功能')
@login_auth
def login():
print('登录功能')
@login_auth
def transfer():
print('转账功能')
@login_auth
def withdraw():
print('提现功能')
register()
login()
transfer()
withdraw()
多层装饰器
def outter1(func1):
print('加载了outter1')
def wrapper1(*args, **kwargs):
print('执行了wrapper1')
res1 = func1(*args, **kwargs)
return res1
return wrapper1
def outter2(func2):
print('加载了outter2')
def wrapper2(*args, **kwargs):
print('执行了wrapper2')
res2 = func2(*args, **kwargs)
return res2
return wrapper2
def outter3(func3):
print('加载了outter3')
def wrapper3(*args, **kwargs):
print('执行了wrapper3')
res3 = func3(*args, **kwargs)
return res3
return wrapper3
@outter1 # index = outer1(wrapper2),加载了outer1
@outter2 # wrapper2 = outer2(wrapper3),加载了outer2
@outter3 # wrapper3 = outer3(index),加载了outer3
def index():
print('from index')
# 语法糖会将紧挨着的被装饰对象的名字当做参数自动传入装饰器函数中
# 多层语法糖解读顺序是先看语法糖有几个,然后再由下往上去看,遇到最后一个才会使用相同的变量名传给装饰器函数使用
# 执行顺序就是:wrapper1>>>>>wrapper2>>>>>wrapper3
# 加载outer3>>>加载outer2>>>加载outer1>>>index()>>>运行wrapper1函数体代码
# >>>然后再执行outer2函数体代码>>>然后再执行wrapper3的函数体代码
有参装饰器
def outer(condition,type_user):
def login_auth(func_name): # 这里不能再填写其他形参
def inner(*args, **kwargs): # 这里不能再填写非被装饰对象所需的参数
username = input('username>>>:').strip()
password = input('password>>>:').strip()
# 校验用户数据,数据的来源有很多种,比如全局字典,全局列表,文本文件,数据库
# 数据的来源不同,处理方式不同,对应的代码编写就不一样
# 分支结构处理,然后根据不同的参数提示,匹配不同的流程
if type_user =='jason':print('VIP')
if condition == '列表':
print('使用列表作为数据来源 比对用户数据')
elif condition == '字典':
print('使用字典作为数据来源 比对用户数据')
elif condition == '文件':
print('使用文件作为数据来源 比对用户数据')
else:
print('去你妹的 我目前只有上面几种方式')
return inner
return login_auth
@outer('文件','jason') # # 左侧是语法糖结构,右侧是函数名加括号结构,先执行函数调用'outer('文件','jason')',返回值是login_auth,再执行语法糖结构'@login_auth'
def index():
print('from index')
index()
"""
我们以后遇到的最复杂的装饰器就是上面的 不会比上面更复杂
目的仅仅是为了给装饰器代码传递更多额外的数据
"""
递归函数
概念:函数直接或者间接调用了自己>>>:递归调用
递归调用:直接调用
def index():
print('from index')
index()
index()
递归调用:间接调用
def index():
print('from index')
func()
def func():
print('from func')
index()
func()
#在python解释器中,递归函数的最大递归数官方是1000,但是实际情况有的是997,998,但是不影响,最大递归深度也能自己设置
#递归函数不应该是无限循环的过程,有两个条件:
1.每次递归,复杂度必须降低
2.必须要有明确的结束条件
递归函数真正的应用场景:
递推:一层层往下寻找答案
回溯:根据已知条件推导最终结果
l1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, ]]]]]]]]]]
# 循环打印出列表中所有的数字
# 1.for循环l1里面所有的数据值
# 2.判断当前数据值是否是数字 如果是则打印
# 3.如果不是则继续for循环里面所有数据值
# 4.判断当前数据值是否是数字 如果是则打印
# 5.如果不是则继续for循环里面所有数据值
# 6.判断当前数据值是否是数字 如果是则打印
def get_num(l1):
for i in l1:
if isinstance(i,int):
print(i)
else:
get_num(i)
get_num(l1)
算法之二分法
算法就是解决问题的有效办法,是所有算法里面最简单的算法,
也有人说二分法不是算法
l1 = [11, 23, 32, 45, 65, 78, 90, 123, 432, 467, 567, 687, 765, 876, 999, 1131, 1232]
def get_num(l1, target_num):
# 添加递归函数的结束条件
if len(l1) == 0:
print('不好意思 找不到')
return
# 1.先获取数据集中间那个数
middle_index = len(l1) // 2
middle_value = l1[middle_index]
# 2.判断中间的数据值与目标数据值孰大孰小
if target_num > middle_value:
# 3.说明要查找的数在数据集右半边 如何截取右半边
right_l1 = l1[middle_index + 1:]
# 3.1.获取右半边中间那个数
# 3.2.与目标数据值对比
# 3.3.根据大小切割数据集
# 经过分析得知 应该使用递归函数
print(right_l1)
get_num(right_l1, target_num)
elif target_num < middle_value:
# 4.说明要查找的数在数据集左半边 如何截取左半边
left_l1 = l1[:middle_index]
# 4.1.获取左半边中间那个数
# 4.2.与目标数据值对比
# 4.3.根据大小切割数据集
# 经过分析得知 应该使用递归函数
print(left_l1)
get_num(left_l1, target_num)
else:
print('找到了', target_num)
get_num(l1, 999)
"""
二分法缺陷
1.数据集必须是有序的
2.查找的数如果在开头或者结尾 那么二分法效率更低!!!
"""
作业
1.尝试编写有参函数将多种用户验证方式整合到其中
直接获取用户数据比对
数据来源于列表
数据来源于文件
list = ['jason', '123']
def outer(condition):
def login_auth(func_name):
def inner(*args, **kwargs):
username = input('username:').strip()
password = input('password:').strip()
if condition == '列表':
print('数据来源于列表')
if username == list[0] and password == list[1]:
res = func_name(*args, **kwargs)
return res
elif condition == '文件':
print('数据来源于文件')
with open (r'username', 'rt', encoding='utf8')as f:
for i in f:
name = i.strip().split(',')
if username == name[0] and password == name[1]:
res = func_name(*args, **kwargs)
return res
else:
print('没有这种方式')
return inner
return login_auth
@outer('文件')
def index():
print('登录成功')
index()
2.尝试编写递归函数
推导指定某个人的正确年龄
eg: A B C D E 已知E是18 求A是多少
def age(n):
if n == 1:
return 18
else:
return age(n-1)+2
print(age(5))
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了