ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python中装饰器的使用

2021-07-30 23:33:02  阅读:158  来源: 互联网

标签:return 函数 python record 使用 装饰 def log


一、背景

python中最为重要的一个概念就是装饰器,这里记录一下原理和方法。从flask源码出发编写一个日志的装饰器。
1.1 装饰器的类型

  • 函数式装饰器
  • 类装饰器

二、装饰器原理与使用

装饰器实际是将函数作为参数传入到另一个函数中,并且可以执行传入的函数。这使得装饰器能够将很多统一流程或者是重复的内容集成在一起。
2.1 flask中的装饰器
flask的路由就是使用装饰器完成的,这里查看一下它的源码

"""
使用例子
@app.route('/')
def index():
	return 'Hello World'
	
# 源码:
""" 前面是整个Flask Object"""
def route(self, rule, **options):
    def decorator(f):
        endpoint = options.pop('endpoint', None)
        # 将其注册到视图中
        self.add_url_rule(rule, endpoint, f, **options)
        return f
    return decorator
"""
1.route部分:
    其中route中rule是接收路由参数,因此可以知道,通过使用装饰器的语法糖@装饰名在里面传递参数,因此我们可以通过这个方法去记录日志的等级。
2.decorator部分:
	将获取到的参数传递给add_url_rule添加规则,其中rule是路由,endpoint是默认的视图,f是编写传进来的函数,也就是自己编写路由完成的功能。因此使用闭包的形式将整个装饰器执行。
总结:
	根据上述的源码可以知道使用闭包完成了整个装饰过程,并且装饰器执行的时候就会执行闭包的函数,因此在闭包中直接执行f()也是可以完成函数的执行。

2.2 实现一个日志管理
根据上述的总结按照以下的步骤就可以实现一个日志装饰器

1.编写日志的抽象函数
2.使用装饰器通过参数传递,确定日志类型
3.执行被装饰的函数,同时反序列化。

代码如下:

def log(path, **kwargs):
    """
    :param path:日志的路径
    :param kwargs: 其余的日志参数
    :return:
    """

    def decorator(f):
        statue = kwargs.pop("statue", "logging")  # 默认的日志等级是logging
        # 输出代替反序列化
        print("已存储函数%s,等级:%s" % (f.__name__, statue))
        print("函数参数个数{0},函数返回值{1}".format(f.__code__.co_argcount, f.__defaults__))
        print("函数参数参数名{0}".format(f.__code__.co_varnames))
        print(f(10, 9))
        return f

    return decorator

@log("/one.txt")
def one_record(a, b):
    """
    这个函数执行的内容
    :param b: int
    :param a: int
    :return: sum
    """
    return a + b

@log("/two.txt", statue="danger")
def two_record(a, b):
    """
    :param a: int
    :param b: int
    :return: sub
    """
    return abs((a - b))

结果

输出结果:
已存储函数one_record,等级:logging
函数参数个数2,函数返回值None
函数参数参数名('a', 'b')
19
已存储函数two_record,等级:danger
函数参数个数2,函数返回值None
函数参数参数名('a', 'b')
1

2.3 多个装饰器的使用
使用多个装饰器的时候,只需要继续在前面添加语法糖就可,实例如下:

# 新加一个带装饰函数
def path(**kwargs):
    def warp(f):
        print(f.__name__)
        return f

    return warp

# 执行顺序是log-->path,相当于one_record=path(log(one_record))
@path()
@log("/one.txt")
def one_record(a, b):
    """
    这个函数执行的内容
    :param b: int
    :param a: int
    :return: sum
    """
    return a + b

2.4 装饰器的测试
为了检验结果,需要写一些测试用例证明装饰器的正确性,下面介绍一下编写的过程。

# 这就是正常调函数的结果
fun_res = one_record(1, 3)
# 这个是装饰器调用的结果
# log是装饰的函数,one_record是被装饰的函数, (1, 3)表示函数中的值,因为log中的闭包需要一个函数类型,因此先将函数传递进去,再将参数传递进去。
dec_rest = log("12")(one_record)(1, 3)
# 进行真假值的判断。
print(fun_res == dec_rest)

三、总结

装饰器在python中是一个比较重要的内容,其核心思想就是利用python可以传递函数的特性,将函数作为参数进行传递,实现的关键部分是使用函数的闭包来完成装饰的过程。在实现测试的时候使用原函数和装饰函数的调用进行结果判断即可。

标签:return,函数,python,record,使用,装饰,def,log
来源: https://www.cnblogs.com/future-dream/p/15082954.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有