内容概览
- 多层装饰器
- 有参装饰器
- 递归函数
- 算法之二分法
多层装饰器
"""多层装饰器的运行流程"""
def outer1(func1): # func1 == inner2
print('outer1运行')
def inner1(*args, **kwargs): # 2 调用function函数先执行之一段
print('inner1运行')
res = func1(*args, **kwargs) # 3 调用inner2函数
print('inner1结束')
return res # 11 函数执行结束
return inner1
def outer2(func2): # func2 == inner3
print('outer2运行')
def inner2(*args, **kwargs): # 4 执行inner2
print('inner2运行')
res = func2(*args, **kwargs) # 5 调用inner3
print('inner2结束')
return res # 10 函数执行结束,返回上层函数
return inner2
def outer3(func3): # func3 == function
print('outer3运行')
def inner3(*args, **kwargs): # 6 执行inner3
print('inner3运行')
res = func3(*args, **kwargs) # 7 执行原function函数
print('inner3结束')
return res # 9 函数执行结束,返回上层函数
return inner3
# 语法糖叠加的情况,会将最上边的值赋给原函数名
# 语法糖会将下边最近的函数名当做参数传给装饰的函数
@outer1 # 这里是最上边的语法糖了,所以将原函数名重新赋值 function = outer1(inner2)
@outer2 # 因为下边又返回了一个函数名,所以这句等同于 inner2 = outer2(inner3)
@outer3 # 等同于 inner3 = outer3(function) 先运行函数
def function(): # 8 执行function函数
print('function')
function() # 1 这里相当于运行的是inner1
"""
outer3运行
outer2运行
outer1运行
inner1运行
inner2运行
inner3运行
function
inner3结束
inner2结束
inner1结束
"""
有参装饰器
如果需要在装饰器内添加额外的可以从外控制的变量,而且不改变愿代码的调用方式,就需要使用到有参装饰器了
def outer(func_name): # 如果使用语法糖,这里不能添加变量,因为语法糖只能传入一个变量
def inner(*args, **kwargs): # 这里也不能传入变量,因为会改变函数的调用方式
if data: # 假设需要传入一个变量作为条件
print('功能1')
res = func_name()
return res
return inner
@outer
def fn():
print('fn')
fn()
"""不能使用直接传参的方式,还能使用闭包函数来传参"""
def closure(data): # 在这里将需要的一个或多个参数传入
def outer(func_name):
def inner(*args, **kwargs):
if data:
print('功能1')
res = func_name()
return res
return inner
return outer # 将装饰器返回
@closure(123) # 函数加括号优先运行函数,结果返回的是outer,这里就等同于@outer
def fn():
print('fn')
fn()
递归函数
# 递归函数:函数直接或者间接的调用了自己
# 直接调用:
def fn():
print('fn')
fn()
fn() # 在函数内无限调用自己, 最后超过了最大递归次数,报错
# 间接调用:
def fn1():
print('fn1')
fn2()
def fn2()
print('fn2')
fn1()
fn1() # 两个函数相互无限调用,最后也会报错
"""
递归函数的正确使用方式
1.每调用一次都要比上一次简单
2.需要有一个明确的结束条件
"""
l1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, ]]]]]]]]]]
"""循环打印l1内所有数字"""
def get_num(vessel):
for i in vessel:
if i 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(vessel, num): # 将数据和选定的数字传入
if len(vessel) == 0: # 加入结束条件,如果列表长度为零还没有找到数字则结束
print('没有这个数字')
return
num_index = len(vessel) // 2 # 整除得到中间数下标
mediant = vessel[num_index] # 通过下标获取数字
if num > mediant: # 判断指定数字是否大于中间数
r_vessel = vessel[num_index + 1:] # 获取中间数开始往后的所有数
get_num(r_vessel, num) # 传入剩下的数据值和选定的数字在执行一次函数
elif num < mediant: # 判断指定数字是否小于中间数
l_vessel = vessel[:num_index] # 获取从开头到中间数的所有数字
get_num(l_vessel, num) # 传入剩下的数据值和选定的数字在执行一次函数
else: # 如果不大不小,就代表找到数字了
print('找到了', vessel[num_index])
get_num(l1, 999)
"""使用二分法,数据的数据值必须是有序的"""
练习
from functools import wraps
""""
1.尝试编写有参函数将多种用户验证方式整合到其中
直接获取用户数据比对
数据来源于列表
数据来源于文件
"""
user_info = ['jason', '321']
flag = ['0']
def outer(data_type):
def judge(func):
@wraps(func)
def inner(*args, **kwargs):
if flag[0] == '1':
res = func(*args, **kwargs)
return res
username = input('username:').strip()
password = input('password:').strip()
if data_type == 'file':
with open(f'userinfo.txt', 'r', encoding='utf8') as f:
for i in f:
dict_user, dict_pwd = i.split(',')
if dict_user == username and dict_pwd.rstrip() == password:
print('登录成功')
flag[0] = '1'
res = func(*args, **kwargs)
return res
else:
print('用户名或密码错误')
return
elif data_type == 'list':
if username == user_info[0] and password == user_info[1]:
print('登录成功')
flag[0] = '1'
res = func(*args, **kwargs)
return res
else:
print('用户名或密码错误')
return
else:
if username == 'jason' and password == '123':
print('登录成功')
flag[0] = '1'
res = func(*args, **kwargs)
return res
else:
print('用户名或密码错误')
return inner
return judge
choice_type = input('请选择验证方式:file/list/默认').strip()
@outer(choice_type)
def register():
print('注册功能')
@outer(choice_type)
def login():
print('登录功能')
@outer(choice_type)
def transfer():
print('转账功能')
@outer(choice_type)
def withdraw():
print('取款功能')
while True:
func_dict = {'1': register, '2': login, '3': transfer, '4': withdraw}
choise = input("""
1.注册
2.登录
3.转账
4.取钱
请选择:""").strip()
if choise in func_dict:
func_dict[choise]()
else:
print('输入有误')
"""
2.尝试编写递归函数
推导指定某个人的正确年龄
eg: A B C D E 已知E是18 求A是多少
"""
def get_age(num):
if num > 1:
return 2 + get_age(num-1)
else:
return 18
print(get_age(5))