叠加装饰器和补充部分

叠加装饰器

   叠加装饰器:
    在同一个被装饰对象中,添加多个装饰器,并执行。
    @装饰1
    @装饰2
    @装饰3
    def 被装饰对象():
        pass
    注意:装饰器在调用被装饰对象时才会执行添加新功能。

    - 叠加装饰器:
        - 装饰的顺序: 由下到上装饰
        - 执行的顺序: 由上往下
注意:无论inner中出现让任何的判断,最后的都要返回”调用后的装饰对象“func(*args, **kwargs)

def wrapper1(func):
    def inner1(*args, **kwargs):
        print('1---start')
        res = func(*args, **kwargs)#被装饰对象在调用时,如果还有其他inner,会先执行其他装饰器中的inner
        print('1---end')
        return res
    return inner1

def wrapper2(func):
    def inner2(*args, **kwargs):
        print('2---start')
        res = func(*args, **kwargs)
        print('2---end')
        return res
    return inner2

def wrapper3(func):
    def inner3(*args, **kwargs):
        print('3---start')
        res = func(*args, **kwargs)
        print('3---end')
        return res
    return inner3

@wrapper1 #inner1 = wrapper1(inner2)
@wrapper2 #inner2 = wrapper2(inner3)
@wrapper3 #inner3 = wrapper3(index)
def index():
    print('from the index>>>>>')
index()
>>>>>>>>>
1---start
2---start
3---start
from the index>>>>>
3---end
2---end
1---end

装饰器的分类

# 无参装饰器: 装饰在被装饰对象时,没有传参数的装饰器。
'''
# 以下是无参装饰器
@wrapper1  # inner1 = wrapper1(inner2)
@wrapper2  # inner2 = wrapper2(inner3)
@wrapper3
'''

# 有参装饰器: 装饰被装饰的对象时,有传参的装饰器
在某些时候,我们需要给用户的权限进行分类
'''
# 以下是有参装饰器
@wrapper1(参数1)  # inner1 = wrapper1(inner2)
@wrapper2(参数2)  # inner2 = wrapper2(inner3)
@wrapper3(参数3)
'''

def user_auth(user_role):
    '''
    有参装饰器函数
    '''
    
    def wrapper(func):
        def inner(*args, **kwargs):
            if user_role == 'vip':
                print('welcome!')
                res = func(*args, **kwargs)
                return res
            elif user_role == '普通用户':
                print('hi')
                res = func(*args, **kwargs)
                return res
        return inner
    return wrapper
@user_auth('普通用户')  # wrapper = user_auth('普通用户')--->相当于@wrapper 语法糖

def ndex():
    pass
index()
>>>>>>>
hi
wraps 的补充

wraps :是一个修复工具,修复的是被装饰对象的空间

from functools import wraps


def wrapper(func):
    def inner(*args, **kwargs):
        '''
        此处是装饰器的注释
        :param func:
        :return:
        '''
        res = func(*args, **kwargs)
        return res
    return inner  # ---》 func


@wrapper
def index():
    '''
    此处是index函数的注释
    :return:
    '''
    pass


print(index)  # 函数对象

# 函数对象.__doc__: 查看函数内部的注释
print(index.__doc__)  # inner.__doc__
>>>>>>>
<function wrapper.<locals>.inner at 0x000002A0A52A7C80>

        此处是装饰器的注释
        :param func:
        :return:

下面是使用了wraps后的 修复被装饰对象空间,下面是被装饰对象的注释

def wrapper(func):
 
    @wraps(func)  # 修改名称空间: inner ---》 func  此处修改成功
    def inner(*args, **kwargs):   
        '''
        此处是装饰器的注释
        :param func:
        :return:
        '''
        res = func(*args, **kwargs)
        return res
    return inner  # ---》 func


@wrapper
def index():
    '''
    此处是index函数的注释
    :return:
    '''
    pass


print(index)  # 函数对象

# 函数对象.__doc__: 查看函数内部的注释
print(index.__doc__)  # inner.__doc__
>>>>>>>>>>>>
<function index at 0x00000199BCC77C80>

    此处是index函数的注释
    :return:
    

编写装饰器 为多个函数加上认证的功能(用户的账号i密码来源于文件)要求登录一次,后续的函数无需再输入用户名和密码。

# 可变类型,无需通过global引用,可直接修改
user_info = {
    'user': None  # username
}

# 不可变类型,需要在函数内部使用global对其进行修改
user = None

def login():
    # 判断用户没有登录时,执行
    # 登录功能
    # global user
    username = input('请输入账号: ').strip()
    password = input('请输入密码: ').strip()
    with open('user.txt', 'r', encoding='utf-8') as f:
        for line in f:
            print(line)
            name, pwd = line.strip('
').split(':')  # [tank, 123]

    if username == name and password == pwd:
        print('登录成功!')
        user_info['user'] = username
    else:
        print('登录失败!')


def login_auth(func):  # func ---> func1, func2, func3
    def inner(*args, **kwargs):
        # 已经登录,将被装饰对象直接调用并返回
        if user_info.get('user'):
            res = func(*args, **kwargs)  # func() ---> func1(), func2(), func3v
            return res

        # 若没登录,执行登录功能
        else:
            print('请先登录...')
            login()

    return inner


# func1,2,3 都需要先登录才可以使用,若登录一次,
# 后续功能无需再次登录,绕过登录认证
@login_auth
def func1():
    print('from func1')
    pass


@login_auth
def func2():
    print('from func2')
    pass


@login_auth
def func3():
    print('from func3')
    pass


while True:
    func1()
    input('延迟操作...')
    func2()
    func3()
>>>>>>>>>>>>>
请输入你的账户:david
请输入你的密码:123
登录成功
{'user': 'david'}
from func1
延迟操作
from func2
from func3
from func1
延迟操作

# 无参装饰器模板
def wrapper(func):
    def inner(*args, **kwargs):
        res = func(*args, **kwargs)
        # 在被装饰对象调用后添加功能
        return res
    return inner


# 有参装饰器模板
def outer(arg):
    def wrapper(func):
        def inner(*args, **kwargs):
            res = func(*args, **kwargs)
            return res

        return inner
    return wrapper
原文地址:https://www.cnblogs.com/bs2019/p/11858648.html