day03.21
多层装饰器
语法糖会将紧挨着的被装饰对象的名字当做参数自动传入装饰器函数中。多层装饰器的执行顺序是自上而下顺序执行。
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 @outter2 @outter3 def index(): print('from index')
有参装饰器
有参装饰器需要再加一层封装,需要在无参装饰器的外部在嵌套一个函数。
def outer(source_data): def login_auth(func_name): # 不能动 只能接收一个被装饰对象名字 def inner(*args, **kwargs): # 不能动 是专门用来给被装饰的对象传参的 username = input('username>>>:').strip() password = input('password>>>:').strip() # 校验用户数据 数据的来源可以有很多 比如全局字典 全局列表 文本文件 数据库 # 数据的来源不同 处理方式就不同 对应的代码编写就不一样 # 分支结构处理 然后根据不同的参数提示 匹配不同的流程 if source_data == '1': print('使用字典的方式处理数据') elif source_data == '2': print('使用列表的方式处理数据') elif source_data == '3': print('使用文件操作处理数据') else: print('其他操作情况') res = func_name(*args, **kwargs) return res return inner return login_auth
递归函数
递归函数的解释:
在python编程语言当中,函数运行的过程中,直接或间接调用函数本身,则该函数称为递归函数。即在每一次计算的时候都需要用到上一次计算的结果。
递归函数的优点是逻辑简单清晰;缺点是过度的调用会占取很大的内存空间。
直接调用:
def index(): print('from index') index() index()
间接调用:
def index(): print('from index') func() def func(): print('from func') index() func()
NOTE:
函数的递归不应该是无限循环的过程,真正的递归函数需要满足两个要求:
- 每次递归结束,其复杂度必须降低,即下一次递归要比上一次递归要简单
- 递归必须要有明确的结束条件
一般情况下,python编程语言当中的递归函数是有最大递归深度的,超出了这个最大递归深度,python解释器就会有一个预警机制,会提示超出最大递归深度。
import sys print(sys.getrecursionlimit()) # 获取默认的最大递归深度 # 1000 sys.setrecursionlimit(2000) # 还可以修改最大递归深度 count = 1 def index(): print('from index') global count print(count) count += 1 index() index()
总的来说, 递归函数的实质就是自己调用自己。在下一次对自己的调用之前,函数把参数值根据某种对应法则进行了改变,从而将改变后的结果作为下一次调用的参数。
eg:
def get_age(n): if n == 1: return 18 # 有明确的结束条件 return get_age(n - 1) + 2 print(get_age(4))
l1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, ]]]]]]]]] def get_num(l): for i in l: # 自带结束条件 并且每次传入的数据都比上一次简单 if isinstance(i, int): # 判断某个数据是否属于某个类型 print(i) else: get_num(i) get_num(l1)
算法之二分法
算法就是指解决问题的办法,研究算法的过程就是寻求解决问题的最佳办法的过程,目前并没有出现最优解的算法。
二分法的原理:
二分法是一种查找算法,二分法的使用前提就是数据集合必须有先后顺序,即升序或降序。
获取数据集中间的元素,比对大小;如果中间的元素大于目标数据,那么保留数据集的左边一半;如果中间的元素小于目标数据,那么保留数据集的右边一半;
然后针对剩下的数据集再二分;如果中间的元素大于目标数据,那么保留数据集的左边一半;如果中间的元素小于目标数据,那么保留数据集的右边一半;
以此类推,直到找到你想找的元素。
eg:
l1 = [13, 21, 35, 46, 52, 67, 76, 87, 99, 123, 213, 321, 432, 564, 612] def get_target(l1, target_num): # 最后需要考虑找不到的情况 l1不可能无限制二分 if len(l1) == 0: print('不好意思 真的没有 找不到') return # 1.获取中间元素的索引值(只能是整数) middle_index = len(l1) // 2 # 2.判断中间索引对应的数据与目标数据的大小 if target_num > l1[middle_index]: # 3.保留数据集右侧 l1_left = l1[middle_index + 1:] # 3.1.对右侧继续二分 重复执行相同代码 并且复杂度降低 print(l1_left) get_target(l1_left, target_num) elif target_num < l1[middle_index]: # 4.保留数据集左侧 l1_right = l1[:middle_index] print(l1_right) # 4.1.对右侧继续二分 重复执行相同代码 并且复杂度降低 get_target(l1_right, target_num) else: print('找到了', target_num) get_target(l1, 13)
二分法的局限性:
二分法取值的数据必须要有顺序;如果取值在数据集合的前列,二分法将不再简便快捷。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?