昨日内容回顾
定义在函数内部的函数并且使用了外包函数局部名称空间中的名字
闭包函数给我们提供了另外一种传参方式
装饰器不改变源代码不改变被装饰对象调用方式才能称为装饰器
1.统计某个函数的运行时间
2.将统计函数运行时间的代码封装成函数
3.直接封装的函数会改变调用方式
4.利用闭包函数传参尝试
5.利用重名替换原来的函数名的功能
6.函数的参数
7.函数的返回值
def outer(func_name)
def inner(*args,**kwargs)
res = func_name(*args,**kwargs) # 这个就是被装饰函数执行的地方
return res
return inner #此处返回值需是组成装饰器第二个函数
"""
针对两个地方的*args和**kwargs的作用
def index(*args,**kwargs):
pass
def func(*args,**kwargs):
index(*args,**kwargs)
func([1,2,3,4],name='jason',age=18)
"""
@后面跟第一个定义的函数包装饰器第一个函数
def home():
pass
honme= outer(home)
home()
from functools import wraps
def outer(func_name):
@wraps(func_name)
def inner(*args, **kwargs):
print('jason')
res = func_name(*args, **kwargs)
print('tony')
return res
return inner
@outer
def user_name():
print('kiven')
user_name()
今日内容概要
- 多层装饰器
- 有参装饰器
- 递归函数
- 算法
- 三元表达式
今日内容详细
升级版作业
is_login = {'is_login': False} #1.定义状态栏
from functools import wraps # 装饰器修复技术
def login_auth(func_name): # 2.编写装饰器
@wraps(func_name)
def inner(*args,**kwargs): #4.装饰器二层函数使用第一层函数返回值调用
if is_login.get('is_login'): # 按k取 如果成立则不走下面代码直接执行被装饰函数然后结束
res = func_name(*args, **kwargs) # 被装饰函数调用位置
return res #被调用函数调用后返回值
user_name = input('输入用户名>>>:').strip() # 6.获取用户输入
pwd = input('输入用户密码>>>:').strip() #7.
if user_name == 'jason' and pwd == '123': #8.
res = func_name(*args, **kwargs) #9. 被装饰函数执行
is_login['is_login'] = True # 10.校验成功一次后会将字典中的值改为成立
return res #11. 这是被装饰函数的返回值没有return此时返回值为None
else:
print('权限不足')
return inner #5.返回函数名到外部 此时外层调用的函数是inter函数
@login_auth
def register(): #3.调用函数
print('注册功能')
@login_auth
def login():
print('登陆功能')
@login_auth
def transfer():
print('转账功能')
@login_auth
def withdraw():
print('提现功能')
register() # inter函数
login()
transfer()
withdraw()
print(register()) # 内层函数处返回的是函数名便可以使用 如果返回的不是
# 被装饰函数名则这个返回值是被包函数的返回值被函数就
#第二层函数,被装饰函数是下面定义的函数有装饰语法糖的函数
多层装饰器
def outter1(func1):
print('加载了outter1')
def wrapper1(*args, **kwargs): #1 wrapper1
print('执行了wrapper1')
res1 = func1(*args, **kwargs) #2 wrapper2
return res1
return wrapper1 # index
def outter2(func2):
print('加载了outter2')
def wrapper2(*args, **kwargs): # 3
print('执行了wrapper2')
res2 = func2(*args, **kwargs) #4
return res2
return wrapper2
def outter3(func3): # 1
print('加载了outter3')
def wrapper3(*args, **kwargs):# 5
print('执行了wrapper3')
res3 = func3(*args, **kwargs) #6
return res3
return wrapper3
# @outter4 # index = outter4(wrapper1) index是wrapper1
@outter1 # index = outter1(wrapper2)
@outter2 # wrapper2 = outter2(wrapper3)
@outter3 # wrapper3 = outter3(index)
def index():
print('from index')
index() #此调用为wrapper1
有参函数
def login_auth(func_name):
def inner(*args, **kwargs):
username = input('username>>>:').strip()
password = input('password>>>:').strip()
if username == 'jason' and password == '123':
res = func_name(*args, **kwargs)
return res
else:
print('用户权限不够 无法调用函数')
return inner
"""
需求:在装饰器内部可以切换多种数据来源
列表
字典
文件
"""
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')
def index():
print('from index')
index()
"""
我们以后遇到的最复杂的装饰器就是上面的 不会比上面更复杂
目的仅仅是为了给装饰器代码传递更多额外的数据
"""
递归函数
概念
函数直接或间接调用直接
# 递归调用,直接调用
def index()
print('from index
index()
#简介调用
def index()
print('from index')
func()
def func()
print('from func')
index()
func()
'''
python中允许函数最大递归调用次数
官方给出是1000 用代码验证是996 或 997
有偏差
'''
count = 0
def func():
print('from func')
global count
count += 1
print(count)
index()
def index():
print('from index')
func()
index()
# import sys
#
# sys.setrecursionlimit(2000) 修改递归调用次数
#
# print(sys.getrecursionlimit()) 查询递归次数
#
"""
递归函数真正的应用场景
递推:一层层往下寻找答案
回溯:根据已知条件推导最终结果
递归函数
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)
![image]()
算法二分法
什么是算法
算法就是解决问题的方法
算法永远都在精进 但是很少有最完美的算法
算法很多时候可能没什么用
小公司一般不会有算法工程师 只有大公司才会有
算法工程师待遇很高 但是产出很少 甚至几年几十年都没有成果
有点相当于科研人员
很多大型互联网面试都喜欢问算法
平时学有余力可以简单看看(临时抱佛脚)
二分法 快拍 插入 堆排 链表 双向链表 约瑟夫问题
二分法
是所有算法里面最简单的算法
也有人说二分法不是算法
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)
get_num(l1, 1000)
"""
二分法缺陷
1.数据集必须是有序的
2.查找的数如果在开头或者结尾 那么二分法效率更低!!!
"""
l1 = [11, 23, 32, 45, 65, 78, 90, 123, 432, 467, 567, 687, 765, 876, 999, 1131, 1232] # 定义列表
# 先获取数据中间的数据
def func(l1,tanger_num):
if len(l1) == 0: # 如果切到为0无法切直接结束
print('木有你要找到数字')
return
num = len(l1)//2 # len出数据个数一分为二 索引位数
index_num = l1[num] #取到索引中间的一个数
if tanger_num > index_num: # 拿我们要的数据值和拿到的数据做比对 如果da说明数据在右边
right_l1 = l1[num+1:] # 将列表一分为二 列表索引个数加一从索引位数出加一冒号切到末尾
print(right_l1)
func(right_l1,tanger_num) # 再次调用函数 将切割后的列表当参数传入将比对的数据也传入再走一次流程
elif tanger_num < index_num:
left_l1 = l1 [:num]
print(left_l1)
func(left_l1,tanger_num)
else:
print('找到了',tanger_num)
func(l1,8999)
![image]()
作业
data_dict = {'name': 'kiven', 'pwd': 123}
user_name_list = ['jason|123']
print('''
1.列表
2.字典
3.文件
''')
func_id = input('输入数据认证类型').strip()
def data(chonie):
def ohter(user_name_info):
def func(*args, **kwargs):
user_name = input('请输入用户名>>>:').strip()
password = input('请输入密码>>>:').strip()
if chonie == '1':
real_name, realpwd = user_name_list[0].split('|')
if user_name == real_name and password == realpwd:
onglin = user_name_info(*args, **kwargs)
return onglin
else:
print('认证失败')
elif chonie == '2':
real_name = data_dict.get('name')
real_pwd = data_dict.get('pwd')
real_pwd = str(real_pwd) # 未转字符串比对就会打印多出一步
if user_name == real_name and password == real_pwd: # 密码是字符串 字典里的是整型
onglin = user_name_info(*args, **kwargs)
return onglin
else:
print('认证失败')
elif chonie == '3':
with open(r'a.txt', 'r', encoding='utf8') as f:
k = f.read()
real_name, real_pwd = k.split('|')
if user_name == real_name and password == real_pwd:
onglin = user_name_info(*args, **kwargs)
return onglin
else:
print('认证失败')
else:
print('没有此数据')
return func
return ohter
@data(func_id)
def onglin():
print('认证成功')
onglin()