1. 装饰器后续
"""语法糖会将紧挨着的被装饰对象的名字当做参数自动传入装饰器函数中"""
# 判断print执行顺序
def outer1(real_func1):
print('加载了装饰器1')
def func1(*args, **kwargs):
print('执行了func1')
res1 = real_func1(*args, **kwargs)
return res1
return func1
def outer2(real_func2):
print('加载了装饰器2')
def func2(*args, **kwargs):
print('执行了func2')
res2 = real_func2(*args, **kwargs)
return res2
return func2
def outer3(real_func3):
print('加载了装饰器3')
def func3(*args, **kwargs):
print('执行了func3')
res3 = real_func3(*args, **kwargs)
return res3
return func3
@outer1
@outer2
@outer3
def print_python_cat():
print('from python cat')
print_python_cat()
# >>>: 加载了装饰器3
# >>>: 加载了装饰器2
# >>>: 加载了装饰器1
# >>>: 执行了func1
# >>>: 执行了func2
# >>>: 执行了func3
# >>>: from python cat
2. 有参装饰器
def login_auth(func_name): # 这个参数是用来接收一个被装饰的方法对象名字,是不能发生修改的
def inner(*args, **kwargs): # 这两个参数专门是用来给被装饰的方法对象传参的,是不能发生修改的
# if data == '1':
# print('1111')
# elif data == '2':
# print('2222')
# else:
# print('3333')
res = func_name(*args, **kwargs)
return res
return inner
# 那么我们如何在不修改login_auth的方法的前提,增加对data的输入呢
# 那么我就会想到,之前如何对inner在不修改方法的前提的进行拓展,我们利用闭包函数在外面增加一次进行传入新的参数
# 那么我们现在也可以使用同样的方法,在外面再套一层方法,来进行传值,来解决此问题
def afferent_data(data):
def login_auth(func_name): # 这个参数是用来接收一个被装饰的方法对象名字,是不能发生修改的
def inner(*args, **kwargs): # 这两个参数专门是用来给被装饰的方法对象传参的,是不能发生修改的
if data == '1':
print('1111')
elif data == '2':
print('2222')
else:
print('3333')
res = func_name(*args, **kwargs)
return res
return inner
return login_auth
"""
函数名加括号 执行优先级最高
@outer('3')
左侧是语法糖结构 右侧是函数名加括号结构
先执行函数调用 outer('3') 返回值是login_auth
在执行语法糖结构 @login_auth
发现最后还是一个普通的装饰器
有参装饰器目的仅仅是给装饰器传递额外的参数
装饰器最多就三层嵌套
并且三层嵌套的结构使用频率不高(最多是使用别人写好的有参装饰器)
from functools import wraps
@wraps(func_name)
"""
@afferent_data('3')
def print_python_cat():
print('from print python cat')
print_python_cat()
# >>>3333
# >>>from print python cat
3. 递归函数
# 本质:递归函数也称为函数的递归
# 函数在运行过程中直接或者间接的调用了自身
# 基本演示
# 直接调用自己
def index():
print('from index')
index()
index()
"""
maximum recursion depth exceeded while calling a Python object 最大递归深度超出限制了
python解释器自带的应急机制
在有些编程语言中 没有最大递归深度超出限制了 甚至没有遇警机制 代码执行真的一致到计算机崩溃为止
"""
# 间接调用自己
# def print_python_cat():
# print('from python cat')
# func()
# def python_cat():
# print('from cat')
# print_python_cat()
# python_cat()
"""
maximum recursion depth exceeded while calling a Python object
这对python最大递归深度
回答997 998 1000都可以
官方给出的是1000
"""
import sys
print(sys.getrecursionlimit()) # 获取默认的最大递归深度 # 1000
sys.setrecursionlimit(2000) # 还可以修改最大递归深度
count = 1
def print_python_cat():
print('from python cat')
global count
print(count)
count += 1
print_python_cat()
print_python_cat()
"""
函数的递归不应该是无限循环的过程 真正的递归函数应该要满足两个要求
1.每次递归 复杂度必须降低(下一次递归要比上一次递归解答)
大白话 越往下递归应该离解决问题的答案越近
2.必须要有明确的结束条件
"""
# 诠释
"""
需求:我想知道我们班坐在第一排的某个学生年龄
过程:
我问他多大了 他调皮不告诉我 说比后面那个同学大两岁
后面的说比他后面的大两岁
...
问到最后你一排 终于开口说 18岁
...
知道最后一排的年级回推就可以知道第一排的年级
名词:
递推:一层层往下问
回溯:根据结果推结论
"""
# 如何编写代码完成
# 目标人物的年龄 = 后一排年龄 + 2
# 后一排年龄 = 后后一排年龄 + 2
# 后后一排年龄 = 后后后一排年龄 + 2
# 后后后后一排年龄 = 18
# 将求问年龄变成函数
# age(5) = age(4) + 2
# age(4) = age(3) + 2
# age(3) = age(2) + 2
# age(2) = age(1) + 2
# age(1) = 18
# 封装函数
def get_age(age):
if age == 1:
return 18 # 有明确的结束条件
return get_age(age - 1) + 2
print(get_age(4))
4. 算法之二分法
# 什么是算法?
# 算法其实就是解决问题的有效方法
# 如:比如打开易拉罐的问题
# 方法1:使用金属撬棍
# 方法2:直接手扣
# 方法3:一阳指戳
# ...
"""
算法比较偏向于学术研究 很枯燥 并且产出很少
甚至只有非常大的互联网公司才会有算法部分
算法工程师薪资待遇很高 但是产出很少
有时候甚至几年都没有任何的成果 有点类似于研究所!!!
"""
# 算法之二分法
# 二分法是算法里面最入门的一个 主要是感受算法的魅力所在
"""二分法使用有前提: 数据集必须是有序, 如升序或者降序"""
index_list = [11, 22, 33, 44, 55, 66, 77, 88, 99]
"""
二分法原理
获取数据集中间的元素 比对大小
如果中间的元素大于目标数据 那么保留数据集的左边一半
如果中间的元素小于目标数据 那么保留数据集的右边一半
然后针对剩下的数据集再二分
如果中间的元素大于目标数据 那么保留数据集的左边一半
如果中间的元素小于目标数据 那么保留数据集的右边一半
...
"""
def get_target(index_list, target_num):
# 最后需要考虑找不到的情况 index_list不可能无限制二分
if len(index_list) == 0:
print('不好意思 真的没有 找不到')
return
# 1.获取中间元素的索引值(只能是整数)
middle_index = len(index_list) // 2
# 2.判断中间索引对应的数据与目标数据的大小
if target_num > index_list[middle_index]:
# 3.保留数据集右侧
index_list_left = index_list[middle_index + 1:]
# 3.1.对右侧继续二分 重复执行相同代码 并且复杂度降低
print(index_list_left)
get_target(index_list_left, target_num)
elif target_num < index_list[middle_index]:
# 4.保留数据集左侧
index_list_right = index_list[:middle_index]
print(index_list_right)
# 4.1.对右侧继续二分 重复执行相同代码 并且复杂度降低
get_target(index_list_right, target_num)
else:
print('找到了', target_num)
# 查找一个数 22
get_target(index_list,22)
# 查找一个数 33
get_target(index_list,33)
# 查找一个数 55
get_target(index_list, 55)
"""
二分法的缺陷
1.如果要找的元素就在数据集的开头 二分更加复杂
2.数据集必须有顺序
目前没有最完美的算法 都有相应的限制条件
"""
"""
以后面试的时候 可能会让你手用python写一些算法
二分法 快排 插入 冒泡 堆排序
上述知识面试之前临时抱佛脚即可 平时无需过多研究
"""