美文网首页
Python装饰器

Python装饰器

作者: 木叶苍蓝 | 来源:发表于2020-10-26 16:13 被阅读0次

来源:南枝向暖北枝寒MA
https://blog.csdn.net/mall_lucy/article/details/108791699

装饰器的定义

就是给已有函数增加额外功能的函数,它本质上就是一个闭包函数。
装饰器的功能特点:

  • 不修改已有函数的源代码
  • 不修改已有函数的调用方式
  • 给已有函数增加额外的功能

闭包与装饰器的区分:
如果闭包函数的参数有且只有一个,并且是函数类型,那么这个闭包函数称之为装饰器。写代码要遵循开放封闭原则,它规定已经实现的功能代码不允许被修改,但可以被扩展。

装饰器的示例代码
# 定义装饰器
def decorato(func):
    def inner():
        # 在内部函数里面对已有函数进行装饰
        print("已添加登录认证")
        func()
    return inner

def comment()"
    print("发表评论")

# 调用装饰器对已有函数进行装饰,左边的comment=inner
comment = decorator(comment)

# 调用方式不变
commnet()
装饰器的语法糖写法

如果有多个函数都需要添加登录验证的功能,每次都需要编写func=decorator(func)这样代码对已有函数进行装饰,这种做法还是比较麻烦的。
Python给提供了一个装饰器函数更加简单的写法,那就是语法糖,语法糖的书写格式:@装饰器名称。通过语法糖的方式也可以完成对已有函数的装饰。

# 定义装饰器
def decorator(func):
    def inner():
        # 在内部函数里面对已有函数进行装饰
        print("已添加登录认证")
        func()
    return inner

@decorator  # comment = decorator(comment) 装饰器语法糖对该代码进行了封装,左边comment=inner
def comment():
    print("发表评论")

# 调用方式不变
comment()
装饰器的执行时机

当前模块加载完成以后,装饰器会立即执行,对已有函数进行装饰。

# 定义装饰器
def decorator(func):
    print("装饰器执行了")
    def inner():
        # 在内部函数里面对已有函数进行装饰
        print("已添加登录认证")
        func()
    return inner

@decorator  # comment=decorator(comment)
def comment():
    print("发表评论")
装饰器的使用

装饰器的使用场景

  • 函数执行时间的统计
  • 输出日志信息
装饰器实现已有函数执行时间的统计
import time

def decorator(func):
    def inner():
        # 获取时间距离1970-1-1 0:0:1的时间差
        begin = time.time()
        func()
        end = time.time()
        result = end - begin
        print(f"函数执行完成耗时:{result}")
    return inner

@decorator
def work():
    for i in range(10000):
        print(i)
通用装饰器的使用

通用装饰器:可以装饰任意类型的函数。使用装饰器装饰已有函数的时候,内部函数的类型和要装饰的已有函数的类型保持一致。

装饰带有参数的函数
def decorator(func):
    def inner(num1, num2):
        print("正在努力执行加法运算")
        func(num1, num2)
    return inner

@decorato
def add_num(num1, num2):
    result = num1 + num2
    print(f"结果为:{result}")

add_num(1, 2)
装饰带有参数和返回值的函数
def decorator(func):
    def inner(num1, num2):
        print("正在努力执行加法计算")
        num = func(num1, num2)
        return num
    return inner

@decorator
def add_num(num1, num2):
    result = num1 + num2
    return result

result = add_num(1, 2)
print(f"结果为:{result}")
装饰带有不定长参数和返回值的函数
def decorator(func):
    def inner(*args, **kwargs):
        print("正在努力执行加法计算")
        # *args:把元组里面的每个元素,按照位置参数的方式进行传参
        # **kwargs:把字典里面的每个键值对,按照关键字的方式进行传参
       num = func(*args, **kwargs)
       return num
    return inner

@decorator
def add_num(*args, **kwargs):
    result = 0
    for value in args:
        result += value
    fro value in kwargs.values():
        result += value
    return result

result = add_num(1, 2, a=3)
print(f"结果为:{result}")
多个装饰器的使用

多个装饰器的装饰过程:由内到外的一个装饰过程,先执行内部的装饰器,在执行外部的装饰器

def make_div(func):
    print("make_div装饰器执行了")
    def inner():
        result = '<div>' + func() + '</div>'
        return result
    return inner

def make_p(func):
    print("make_p 装饰器执行了")
    def inner():
        result = '<p>' + func() + '</p>'
        return result
    return inner

# 原理剖析: content = make_div(make_p(content))
# 分布拆解: content = make_p(content),内部装饰器完成, content = make_p.inner
# content = make_div(make_p.inner)

@make_div
@make_p
def content():
    return "人生苦短,我用Python"

c = content()
print(c)

>>> make_p 装饰器执行了
>>> make_div 装饰器执行了
>>><div><p>人生苦短,我用Python</p></div>
带有参数的装饰器

带有参数的装饰器就是使用装饰器装饰函数的时候可以传入指定参数,语法格式:@装饰器(参数...)。使用带有参数的装饰器,其实是在装饰器外面又包裹了一个函数,使用该函数接收参数,返回是装饰器,因为@符号需要配合装饰器实例使用。

def return_decorator(flag):
    # 装饰器只能接收一个参数并且是函数类型
    def decorator(func):
        def inner(a, b):
            if flag == "+":
                print("正在努力执行加法计算")
            elif flag == "-":
                print("正在努力执行减法计算")
            func(a, b)
        return inner
    return decorator

@return_decorator('+') # decorator = return_decorator('+'), @decorator -> add_num = decorator(add_num)

def add_num(a, b):
    result = a + b
    print(result)

@return_decorator("-")
def sub_num(a, b):
    result = a - b
    print(result)

add_num(1, 2)
sub_num(1, 2)
类装饰器的使用

类装饰器:使用类装饰器已有函数

class MyDecorator(object):
    def __init__(self, func):
        self.__func = func
    
    # 实现 __call__ 方法,表示对象是一个可调用对象,可以像调用函数一样进行调用
    def __call__(self, *args, **kwargs):
        # 对已有函数进行封装
        print("马上就要下班啦")
        self.__func()

@MyDecorator  # MyDecorator -> show = MyDecorator(show)
def show():
    print("快要下雪了")

>>> 马上就要下班啦
>>>快要下雪了

函数之所以能够调用,是因为函数内部实现了__call__方法

装饰器应用场景
  • 收集函数的操作和错误日志记录
  • 验证函数的使用权限
  • 计算函数的运行时间
  • 在ORM/DB模块操作时,通过属性方法动态地获取关联的数据
  • 函数数据的缓存
  • 定制函数的输入和输出(序列化和反序列化)

相关文章

  • 装饰器模式

    介绍 在python装饰器学习 这篇文章中,介绍了python 中的装饰器,python内置了对装饰器的支持。面向...

  • python中的装饰器

    python装饰器详解 Python装饰器学习(九步入门) 装饰器(decorator) 就是一个包装机(wrap...

  • [译] Python装饰器Part II:装饰器参数

    这是Python装饰器讲解的第二部分,上一篇:Python装饰器Part I:装饰器简介 回顾:不带参数的装饰器 ...

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • Python进阶——面向对象

    1. Python中的@property   @property是python自带的装饰器,装饰器(decorat...

  • Python 装饰器填坑指南 | 最常见的报错信息、原因和解决方

    Python 装饰器简介装饰器(Decorator)是 Python 非常实用的一个语法糖功能。装饰器本质是一种返...

  • Python装饰器

    Python装饰器 一、函数装饰器 1.无参装饰器 示例:日志记录装饰器 2.带参装饰器 示例: 二、类装饰器 示例:

  • python3基础---详解装饰器

    1、装饰器原理 2、装饰器语法 3、装饰器执行的时间 装饰器在Python解释器执行的时候,就会进行自动装饰,并不...

  • 2019-05-26python装饰器到底是什么?

    装饰器例子 参考语法 装饰器是什么?个人理解,装饰器,是python中一种写法的定义。他仍然符合python的基本...

  • 2018-07-18

    Python装饰器 装饰,顾名思义,是用来打扮什么东西的。Python装饰...

网友评论

      本文标题:Python装饰器

      本文链接:https://www.haomeiwen.com/subject/fmlamktx.html