2.41【Python装饰器】

2023-12-14 20:34:38

Python装饰器

介绍

装饰器可以通俗的理解为在不改变对象原有功能的前提下对其新增额外的功能

装饰器经常用于有切面性要求的场景

  • 插入日志、性能测试、事务处理、缓存、权限校验等应用场景
  • 有了装饰器,就可以抽离出大量与函数本身功能无关的雷同代码并继续重用

分类

无参装饰器

def func1(func):
    def wrapper():
        print("在函数执行之前")
        func()	# 此处执行的就是hello中的代码
        print("在函数执行之后")
    return wrapper

def hello():
    print("Hello, World!")

say_hello = func1(hello)
say_hello()
无参装饰器模板:
def wrapper(func):
    def inner():
        # 第一部分:执行外部传入的函数之前执行的代码
        '''...'''
        # 第二部分:执行外部传入的函数地址(res接受外部函数的返回值,如果有返回值的情况下)
        result = func()
        # 第三部分:执行外部传入的函数之后执行的代码
        '''...'''
        return result
    return inner

该方法仅适用于被装饰的函数没有参数的情况,如果带入参数则会报错

有参装饰器

my_dict = {'name': '张三', 'pwd': '111'}
bank_data = {'张三': {'pwd': '111', 'balance': 1000}}
print(my_dict)
print(bank_data)


def fun1(func):
    def inner(*args, **kwargs):
        if args[1] in my_dict['name']:
            func(*args, **kwargs)
            return True
        else:
            print("用户名不存在")
            return False

    return inner


def fun2(fun):
    def inner(*args, **kwargs):
        if args[2] in my_dict['pwd']:
            fun(*args, **kwargs)
            return True
        else:
            print("密码错误")
            return False
    return inner


def fun3(fun):
    def inner(*args, **kwargs):
        if args[0] < bank_data[args[1]]['balance']:
            fun(*args, **kwargs)
        else:
            print("余额不足")
            return False

    return inner


@fun1
@fun2
@fun3
def balance(sum, name, pwd):
    print(f"歡迎{name}")
    bank_data[name]['balance'] = bank_data[name]['balance'] - sum
    print(f"余额剩余{bank_data[name]['balance']}")


def login(name):
    print(f"欢迎{name}")


balance(100, "张三", '111')	# 根据传入参数判断是否符合标准
# {'name': '张三', 'pwd': '111'}
# {'张三': {'pwd': '111', 'balance': 1000}}
# 歡迎张三
# 余额剩余900
有参装饰器模板:
def big_func(msg):
    def wrapper(func):
        def inner(*args, **kwargs):
            # 在装饰器内部执行操作,可以使用传入的参数 arg1, arg2, ...
            # 这里可以编写装饰器的逻辑
            result = func(*args, **kwargs)
            # 这里可以对结果进行处理或添加额外的操作
            return result
        return inner
    return wrapper

@decorator_with_args(msg='')	# msg填写自己需要传递的参数
def my_func():
    # 函数的实现

无参语法糖

# test1
def func1(func):
    def func2():
        print("在函数执行之前")
        func()
        print("在函数执行之后")
    return func2

@func1
def hello():
    print("Hello, World!")

hello()

# test2
def func1(func):
    def wrapper(*args, **kwargs):
        print("在函数执行之前")
        func(*args, **kwargs)  # 此处执行的就是hello中的代码
        print("在函数执行之后")
    return wrapper

@func1
def hello(name):
    print(f"Hello, {name}!")

hello("Alice") # Hello,Alice!

有参语法糖

def get_card(func):
    def inner(*args, **kwargs):
        global s
        s = user_info['用户名'].index(this_user)
        global card
        card = input("请输入你的银行卡号:")
        if card != user_info['银行卡号'][s]:
            print("卡号不存在,请重试!")
        else:
            return func(*args, **kwargs)

    return inner


def get_pwd(func):
    def inner(*args, **kwargs):
        kpwd = input("请输入您的取款密码:")
        if kpwd != user_info['取款密码'][s]:
            print("密码错误,请重试!")
        else:
            return func(*args, **kwargs)

    return inner


def get_money(func):
    def inner(*args, **kwargs):
        global ksum
        ksum = input("请输入您要取出的金额:")
        if int(ksum) > int(user_info['余额'][s]):
            print("您的余额不足,请重试!")
        else:
            return func(*args, **kwargs)
    return inner


@get_card
@get_pwd
@get_money
def take():
    new_sum = int(user_info['余额'][s]) - int(ksum)
    user_info['余额'][user_info['用户名'].index(this_user)] = str(new_sum)
    w_user(user_info)
    p = 1
    flow(card, ksum, p)
    print(f"您的余额还剩{new_sum}")
    return


take()

伪装装饰器

help()方法会暴露多行注释,存在一定安全隐患,如下:

def wrapper(func):
    '''

    :param func: 传入的函数地址
    :return: 内部的inner地址
    '''

    def inner(*args, **kwargs):
        '''
        # 这是验证登录的装饰器
            --- admin账号:张三
            --- admin密码:666
        :param args: 可变长位置参数
        :param kwargs: 可变长关键字参数
        :return:
        '''
        return func(*args, **kwargs)

    return inner


@wrapper
def add():
    return 1 + 1


help(add)
# Help on function inner in module __main__:
# 
# inner(*args, **kwargs)
#     # 这是验证登录的装饰器
#         --- admin账号:张三
#         --- admin密码:666
#     :param args: 可变长位置参数
#     :param kwargs: 可变长关键字参数
#     :return:

修改后如下:

from functools import wraps


def wrapper(func):
    '''
    :param func: 传入的函数地址
    :return: 内部的inner地址
    '''

    @wraps(func)
    def inner(*args, **kwargs):
        '''

        :param args: 可变长位置参数
        :param kwargs: 可变长关键字参数
        :return:
        '''
        return func(*args, **kwargs)

    return inner


@wrapper
def add():
    return 1 + 1


help(add)
# Help on function add in module __main__:
# 
# add()

文章来源:https://blog.csdn.net/AZURE060606/article/details/134953982
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。