首页 > 其他分享 >装饰器

装饰器

时间:2023-12-13 21:44:21浏览次数:20  
标签:end func time return 装饰 def

装饰器

一、什么是装饰器

  • 通俗的讲就是用来装饰对象的工具,这里被装饰的对象和用来装饰的装饰器都可以可以是任意的课调用的对象
  • 概括的来讲,装饰器就是在不修改被装饰对象的源代码和调用方式的基础下为被装饰对象添加额外的功能

二、装饰器的用途

  • 装饰器在装饰时,应避免修改被装饰对象的源代码和调用方式,否则一但出错,就会产生连锁反应,导致程序崩溃

三、装饰器的分类

  • 装饰器有无参装饰器和有参装饰器,但二者的原理都是一样的,都是”嵌套函数+闭包+函数对象“的组合产物

四、无参装饰器

  • 以添加计算程序时间的装饰器为例
  • 我们将以下装饰对象添加这个功能
import time


def watch():
    time.sleep(1) #为了更清楚的统计时间,让程序停顿一秒
    print("电影看完了!")"
  • 如果不使用装饰器的情况下加上计时功能:
import time


def watch():
    time.sleep(1)
    print("电影看完了!")


start_time = time.time()
watch()
end_time = time.time()
print(f"函数运行经过了{end_time - start_time}秒!")  # 函数运行经过了1.004945993423462秒!
  • 如果我们每次要计算时间时都要重复输入这几行代码会变的很繁琐,所以我们将这个功能同和成一个功能
def _time_(func):
    start_time = time.time()
    func()
    end_time = time.time()
    print(f"函数运行经过了{end_time - start_time}秒!")


_time_(watch)  # 函数运行经过了1.0062942504882812秒!
  • 这样就会改变我们调用指定函数时的调用方式,我们要在使用函数对象时在外面套上一层,再尝试修改
def _time_(func):
    def inner():
        start_time = time.time()
        func()
        end_time = time.time()
        print(f"函数运行经过了{end_time - start_time}秒!")

    return inner


watch = _time_(watch)
watch() 
'''
    电影看完了!
    函数运行经过了1.009092092514038秒!
'''
  • 但当要装饰的函数带有参数时就会报错,所以就有了有参版本的
def _time_(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print(f"程序运行所用时间{end_time - start_time}")
        return res

    return inner


def watch(name, **kwargs):
    time.sleep(2)
    return f"{name}看了电影!"


watch = _time_(watch)
print(watch("Xanadu"))
'''
    程序运行所用时间2.0120654106140137
    Xanadu看了电影
'''
  • 最终我们经过函数的嵌套完成了在不改变函数调用方式和源代码的前提下为函数增加了计算运行所用时间的功能
  • 无参装饰器模板
def outer(func):
    def inner():
        '''这里写调用 func 函数之前的逻辑'''
        res = func()
        '''这里写调用 func 函数之后的逻辑'''
        return res

    return inner


#当被装饰函数有参数时的版本
def wrapper(func):
    def inner(*args, **kwargs):
        # 第一部分:执行外部传入的函数之前执行的代码
        '''...'''
        # 第二部分:执行外部传入的函数地址(res接受外部函数的返回值,如果有返回值的情况下)
        result = func(*args, **kwargs)
        # 第三部分:执行外部传入的函数之后执行的代码
        '''...'''
        return result
    return inner

五、有参装饰器

  • 有参装饰器就是在使用装饰器装饰被装饰对象时会使用传入的参数
def decora(tag):
    if tag == 'time':
        def _time_(func):
            def inner(*args, **kwargs):
                start_time = time.time()
                res = func(*args, **kwargs)
                end_time = time.time()
                print(f"程序运行所用时间{end_time - start_time}")
                return res

            return inner

        return _time_
    if tag == 'end_time':
        def _end_time_(func):
            def outer(*args, **kwargs):
                res = func(*args, **kwargs)
                end_time = time.time()
                print(f"程序运行的结束时间是{end_time}!")

                return res

            return outer

        return _end_time_


    
# 当参数为“end_time”时就会执行装饰器中的打印结束时间的代码
@decora("end_time")
def watch(name, **kwargs):
    time.sleep(2)
    return f"{name}看了电影!"


print(watch("Xanadu"))

'''
    程序运行的结束时间是1702387268.299577!
    Xanadu看了电影!
'''

# 当参数为“time”时,就会执行装饰器中打印运行时间的代码
@decora("time")
def watch(name, **kwargs):
    time.sleep(2)
    return f"{name}看了电影!"


print(watch("Xanadu"))

"""
    程序运行所用时间2.0080788135528564
    Xanadu看了电影!
"""
  • 有参装饰器的模板
def outer(tag):
    #根据输入的tag来判断使用哪个装饰器
    if tag == "xxx":
        def wrapper_1(func):
            def inner():
                res = func
                return res

            return inner

        return wrapper_1
    elif tag == "yyy":
        def wrapper_2(func):
            def inner():
                res = func
                return res

            return inner

        return wrapper_2

六、语法糖

[1]无参语法糖

  • 此时我们就可以用timer来装饰带参数或不带参数的函数了

    • 但是为了简洁而优雅地使用装饰器,Python提供了专门的装饰器语法来取代index=timer(index)的形式
    • 需要在被装饰对象的正上方单独一行添加 @_timer_
    • 当解释器解释到 @_time_ 时就会调用timer函数
    • 且把它正下方的函数名当做实参传入,然后将返回的结果重新赋值给原函数名
    import time
    
    
    def _time_(func):
        def inner(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            end_time = time.time()
            print(f"程序运行所用时间{end_time - start_time}")
            return res
    
        return inner
    
    
    @_time_          # 直接使用@_time_来调用_time_装饰器
    def watch(name, **kwargs):
        time.sleep(2)
        return f"{name}看了电影!"
    
    
    print(watch("Xanadu")) 
    
    '''
        程序运行所用时间2.014646291732788
        Xanadu看了电影!
    '''
    

[2]有参语法糖

def decora(tag):
    if tag == 'time':
        def _time_(func):
            def inner(*args, **kwargs):
                start_time = time.time()
                res = func(*args, **kwargs)
                end_time = time.time()
                print(f"程序运行所用时间{end_time - start_time}")
                return res

            return inner

        return _time_
    if tag == 'end_time':
        def _end_time_(func):
            def outer(*args, **kwargs):
                res = func(*args, **kwargs)
                end_time = time.time()
                print(f"程序运行的结束时间是{end_time}!")

                return res

            return outer

        return _end_time_


    
# 当参数为“end_time”时就会执行装饰器中的打印结束时间的代码
@decora("end_time")
def watch(name, **kwargs):
    time.sleep(2)
    return f"{name}看了电影!"


print(watch("Xanadu"))

'''
    程序运行的结束时间是1702387268.299577!
    Xanadu看了电影!
'''

# 当参数为“time”时,就会执行装饰器中打印运行时间的代码
@decora("time")
def watch(name, **kwargs):
    time.sleep(2)
    return f"{name}看了电影!"


print(watch("Xanadu"))

"""
    程序运行所用时间2.0080788135528564
    Xanadu看了电影!
"""

标签:end,func,time,return,装饰,def
From: https://www.cnblogs.com/taoyuanshi/p/17899968.html

相关文章

  • 装饰器
    装饰器(一)什么是装饰器装饰:代指为被装饰对象添加新的功能。器:代指器具/工具。装饰器与被装饰对象均可以是任意可调用对象。装饰器定义:在不修改被装饰对象源代码和调用方式的前提下为呗装饰对象添加额外的功能。装饰器经常用于有切莫需求的场景插入日志、性能测试、事......
  • 装饰器
    【一】装饰器装饰器(Decorator)是一种用于修改函数或类行为的特殊函数。它可以在不修改原始函数或类定义的情况下,通过添加额外的功能或行为来扩展其功能。装饰器的主要作用是增强函数或类的功能,常见的应用场景包括:函数装饰器:函数装饰器可以在不修改原函数代码的情况下,对函数进行......
  • Python高级之装饰器
    装饰器【一】装饰器介绍装饰器的由来软件的设计应该遵循开放封闭原则,即对扩展是开放的,而对修改是封闭的。对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。对修改封闭,意味着对象一旦设计完成,就可以独立完成其工作,而不要对其进行修改。软件包......
  • 装饰器模式
    装饰器,顾名思义,一个是待装饰者,一个是装饰者,就像我们早餐吃的煎饼,煎饼是待装饰者,其他的火腿、里脊、土豆丝、生菜等都是装饰者,但最终都没有改变这还是一个煎饼。这里代码上有两个重要的点,一个是装饰者会也会继承或者实现被装饰者,第二是装饰者的构造函数会有一个类型为待装饰者的参......
  • 装饰器
    装饰器装饰器的作用就是在不修改被装饰对象源代码和调用方式的前提下为被装饰对象添加额外的功能装饰器经常用于有切面需求的场景插入日志、性能测试、事务处理、缓存、权限校验等应用场景有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用【一】装饰......
  • 装饰器
    装饰器装饰器的作用就是在不修改被装饰对象源代码和调用方式的前提下为被装饰对象添加额外的功能装饰器经常用于有切面需求的场景插入日志、性能测试、事务处理、缓存、权限校验等应用场景有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用【一】装饰......
  • [-007-]-Python3+Unittest+Selenium Web UI自动化测试之@property装饰器默认值设置
    看示例:#!/usr/bin/python3#coding:utf-8__author__='csjin'#定义@property装饰器classPPTListModels(object):def__init__(self):self._tab_name="PPT模板"@propertydefhandle(self):returnself.__handle......
  • 【python基础之装饰器】---装饰器
    title:【python基础之装饰器】---装饰器date:2023-12-1118:54:06updated:2023-12-1214:30:00description:cover:https://home.cnblogs.com/u/dream-ze/【一】什么是装饰器装饰代指为被装饰对象添加新的功能,器代指器具/工具,装饰器与被装饰的对象均可......
  • 七、Harmony OS 之状态装饰器
    @State:@State装饰器的变量拥有其所属组件的状态,可以作为其子组件单向和双向同步的数据源。当其数值改变时,会引起相关组件的渲染刷新。@Prop:@Prop装饰的变量可以和父组件建立单向同步关系,@Prop装饰的变量二hi可变的,但修改不会同步回父组件。@Link:@Link装饰的变量和父组件构建双向......
  • 23种设计模式——装饰者模式
    今天给大家说一下23种设计模式中装饰者模式。一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。这个时候,我们就需要用到装饰者模式了,它可以实现在不增加很多子类的情况下扩展类的功能。概念:装饰者模式(DecoratorPatt......