python有参装饰器的应用

1、有参装饰器的模板

def 有参装饰器(x,y,z):
    def outter(func):
        def wrapper(*args, **kwargs):
            res = func(*args, **kwargs)
            return res
        return wrapper
    return outter

@有参装饰器(1,y=2,z=3)
def 被装饰对象():
    pass

2、对有参装饰器的理解

有参装饰器无非就是普通装饰器外面又包了一层函数定义,为内部的装饰器提供所需的参数。

3、练习题目

1、题目一:

还记得我们用函数对象的概念,制作一个函数字典的操作吗,来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作
代码如下:

user_dict = {}  # 初始函数空字典


def add_in_dict(idx):
    def outer(func):
        def wrapper(*args, **kwargs):
            user_dict.setdefault(idx, (func, func.__doc__))  # 设置key与value 序号idx和(函数地址和函数文档)元祖形式
            return func(*args, **kwargs)

        return wrapper

    return outer


@add_in_dict(0)
def func1():
    """这是函数文档"""
    pass


@add_in_dict(1)
def func2(test_object):
    print(test_object)


func1()
func2(2)
print(user_dict)

运行结果:

/Users/dyh/pythonProject1/bin/python /Users/dyh/PycharmProjects/pythonProject1/文件名/装饰器/将函数加入到字典的装饰器.py
2
{0: (<function func1 at 0x7fa6380caf70>, '这是函数文档'), 1: (<function func2 at 0x7fa6380cd0d0>, None)}

进程已结束,退出代码为 0

2、题目二:

编写不同登录认证方式的装饰器
代码如下:

def auth(db_type):
    def outer(func):
        def wrapper(*args, **kwargs):
            name = input("your name >>>>>>>>>")
            pwd = input("your password >>>>>>>>>>")
            if db_type == 'file':
                if name == 'dyh' and pwd == '123':
                    print('基于文件的验证')
                    return func(*args, **kwargs)
            elif db_type == 'mysql':

                print('基于mysql认证')
                return func(*args, **kwargs)

        return wrapper

    return outer


@auth('mysql')
def software(test):
    print(test)


software(3)

运行结果:

your name >>>>>>>>>dyh
your password >>>>>>>>>>123
基于mysql认证
3

进程已结束,退出代码为 0

3、题目三:

编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到日志文件中,日志文件路径可以指定
注意:时间格式的获取
import time
time.strftime('%Y-%m-%d %X')

代码如下:

import time
from functools import wraps


def log(file_path):
    def outer(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            res = func(*args, **kwargs)
            with open(f"{file_path}", mode='at',
                      encoding='utf-8') as f:
                f.write(f"{time.strftime('%Y-%m-%d %X')} {func.__name__}运行\n")
            return res

        return wrapper

    return outer


@log("/Users/dyh/PycharmProjects/pythonProject1/文件名/装饰器/日志装饰器/日志文件.txt")
def func1(test_args):
    """这是函数文档"""
    print(test_args)


@log("/Users/dyh/PycharmProjects/pythonProject1/文件名/装饰器/日志装饰器/日志文件.txt")
def func2():
    pass


func1(2)
func2()

运行结果如下:

日志文件.txt:
2022-01-13 11:20:15 func2运行
2022-01-13 11:20:22 func1运行
2022-01-13 11:20:22 func2运行
2022-01-13 11:20:24 func1运行
2022-01-13 11:20:24 func2运行
2022-01-13 11:20:25 func1运行
2022-01-13 11:20:25 func2运行
2022-01-13 11:20:37 func1运行
2022-01-13 11:20:37 func2运行
2022-01-13 11:20:38 func1运行
2022-01-13 11:20:38 func2运行

4、有参装饰器的补充

#偷梁换柱,即将原函数名指向的内存地址偷梁换柱成wrapper函数
#        所以应该将wrapper做的跟原函数一样才行
from functools import wraps

def outter(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """这个是主页功能"""
        res = func(*args, **kwargs) # res=index(1,2)
        return res

    # 手动将原函数的属性赋值给wrapper函数
    # 1、函数wrapper.__name__ = 原函数.__name__
    # 2、函数wrapper.__doc__ = 原函数.__doc__
    # wrapper.__name__ = func.__name__
    # wrapper.__doc__ = func.__doc__

    return wrapper

要记住这个系统给我们做好的函数属性赋值装饰器

5、总结

还是要多写多练,入门还有很远,加油!

posted @ 2022-01-13 10:44  Medjay  阅读(73)  评论(3)    收藏  举报