多层语法糖、装饰器、递归函数

多层语法糖

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  # outter1拿到wrapper2,outter1的上层没有语法糖,index = outter1(wrapperw)
@outter2 #outter2拿到wrapper3,wrapper3 = outter3(index)
@outter3 #@outter3紧贴index(),outter3调用index(),返回wrapper3,所以wrapper3 = outter3(index)
def index():
    print('from index')
多层语法糖加载的顺序从下往上执行,
每次执行之后如果上面还有语法糖 则直接将返回值函数名传给上面的语法糖
如果上面没有语法糖了 则变形 index = outter1(wrapper2)

有参装饰器

def outter(x):
    def  outter1(func):
        def wrapper(*args,*kwargs):
            res = func(*args,**kwargs)
            print(x)
            return res
        return wrapper
      return outter1
    
# 通过第三层进行传值,使得有参装饰器可以使用其他参数,实现其他功能。


@outter('a')
#可以被看做
#f1 = outter1(f1)
#f1 = wrapper(*args,**kwargs)

装饰器模板

最常用的无参装饰器
def outer(func_name):
    def inner(*args, **kwargs):
        res = func_name(*args, **kwargs)
        return res
    return inner
@outer
def index():
    pass

不常用的有参装饰器
def outer_plus(mode):
    def outer(func_name):
        def inner(*args, **kwargs):
            res = func_name(*args, **kwargs)
            return res
        return inner
    return outer
@outer_plus('MySQL')
def func():
    pass

装饰器修复技术

由来:使用装饰器有一个小毛病,就是想要查看被装饰器的注释或者名字时,比如使用如下方法时:
print(help(index)) # 查看函数的注释
print(index.__name__) # 查看函数名字符串形式
结果看到的注释不是被装饰器的注释,而是装饰器里面的内部闭包函数的注释。
查看到的函数名字也是装饰器内部函数的名字,调用函数的时候,想看函数的名字和注释,看到的却不是对的。
基于以上情况,Python提供了解决方案,叫做装饰器修复技术。
# def index():
#     """index函数 非常的牛"""
#     pass
# help(index)
# help(len)
from functools import wraps
def outer(func_name):
    @wraps(func_name)  # 仅仅是为了让装饰器的效果更加逼真 平时可以不写
    def inner(*args, **kwargs):
        """我是inner 我擅长让人蒙蔽"""
        res = func_name(*args, **kwargs)
        return res
    return inner
@outer
def func():
    """我是真正的func 我很强大 我很牛 我很聪明"""
    pass
# help(func)
# print(func)
func()

递归函数

递归的特点:
    函数内部自己调用自己。
    必须有出口。
1 必须有一个明确的结束条件。
2 每次进入更深一层递归时,问题规模(计算量)相比上次递归都应有所减少。
3 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出),此时程序会抛出错误:超出最大递归深度。

  递推:像上边递归实现所拆解,递归每一次都是基于上一次进行下一次的执行,这叫递推。
  回溯:则是在遇到终止条件,则从最后往回返一级一级的把值返回来,这叫回溯。
eg:
     #1直接调用
    # def index():
    #     print('from index')
    #     index()
    # index()
    # 间接
    # def index():
    #     print('from index')
    #     func()
    #
    # def func():
    #     print('from func')
    #     index()
    #
    # func()
    '''最大递归深度:python解释器添加的安全措施'''
    # count = 0
    # def index():
    #     global count
    #     count += 1
    #     print(count)
    #     index()
    # index()
    '''官网提供的最大递归深度为1000 我们在测试的时候可能会出现996 997 998'''
    2.递归函数
	 """
    get_age(5) = get_age(4) + 2
    get_age(4) = get_age(3) + 2
    get_age(3) = get_age(2) + 2
    get_age(2) = get_age(1) + 2
    get_age(1) = 18
    """
    def get_age(n):
        if n == 1:
            return 18
        return get_age(n-1) + 2
    res = get_age(5)
    print(res)

作业

1.利用递归函数依次打印列表中每一个数据值
l1 = [1,[2,[3,[4,[5,[6,[7,[8,]]]]]]]]
def get_num(num):
    for i in num:  # 自带结束条件 并且每次传入的数据都比上一次简单
        if isinstance(i, int):  # 判断数据是否属于整型
            print(i)
        else:
            get_num(i)
    return num
get_num(l1)
3.利用有参装饰器编写多种用户登录校验策略
# 校验用户是否登录装饰器
a=1
def outer(mode):
    #mode=1
    def login_auth(func_name):
        def inner(*args, **kwargs):
            username = input('username>>>:').strip()
            password = input('password>>>:').strip()
            if mode == '1':
                print('数据直接写死')
                if username=='jason' and password=='123':
                    print('数据直接写死')
                else:
                    print('登陆失败')
                    return outer(mode)
            elif mode == '2':
                print('数据来源于文本文件')
                with open(r'a.txt','r+',encoding='utf8') as f:
                    for line in f:
                        real_name,real_password=line.split('|')
                        if username==real_name and real_password.strip('\n')==password:
                            print('登录成功')
                        else:
                            print('登陆失败')
            elif mode == '3':
                print('数据来源于字典')
                user_dic={'name':'jason','password':'123'}

                if user_dic.get('name')==username and user_dic.get('password')==password:
                    print('登录成功')
                else:
                    print('登陆失败')
            elif mode == '4':
                print('数据来源于MySQL')
        return inner
    return login_auth
@outer('1')
def index():
    print('from index')
index()
@outer('2')
def func():
    print('from func')
func()
@outer('3')
def fun2():
    print('from fun2')
fun2()
@outer('4')
def fun3():
    print('from fun3')
fun3()



posted @ 2022-10-12 16:55  冰柠檬檬  阅读(36)  评论(0)    收藏  举报