首页 > 其他分享 >装饰器

装饰器

时间:2024-01-13 23:23:49浏览次数:19  
标签:group inside start time print 装饰 def

【一】什么是装饰器

  • 器:工具
  • 装饰:为其他事物添加额外的功能
  • 定义一个函数,这个函数的功能就是用来装饰其他函数的
  • 也就是说这个函数就是用来给其他函数添加额外功能用的

提示:可调用对象有函数,方法或者类,此处我们单以本章主题函数为例,来介绍函数装饰器,并且被装饰的对象也是函数。

【二】开放封闭原则

  • 开放:对拓展功能(增加功能)开放,意思是再源代码不做任何改变的情况下,为其增加功能
  • 封闭:对修改源代码是封闭的
def inside(x,y):
    print(x)
    print(y)
  • 装饰器:在不修改被装饰对象的源代码,也不修改调用方式的前提下,给装饰对象添加新的功能

【三】代码

【1】引入

  • 用王者荣耀的开局语言模拟来引入
import time


def inside(group, s):
    print('欢迎来到王者荣耀')
    print(f'你出生在{group}方阵营')
    print(f'敌军还有{s}秒到达战场')
    time.sleep(s)
    print('全军出击')


inside('红', 5)
"""
欢迎来到王者荣耀
你出生在红方阵营
敌军还有5秒到达战场
全军出击
"""

【2】需求

  • 需要统计程序运行的时间

(1)方案一

import time


def inside(group, s):
    start = time.time()
    print('欢迎来到王者荣耀')
    print(f'你出生在{group}方阵营')
    print(f'敌军还有{s}秒到达战场')
    time.sleep(s)
    print('全军出击')
    end = time.time()
    print(end-start)

inside('红', 2)

"""
欢迎来到王者荣耀
你出生在红方阵营
敌军还有2秒到达战场
全军出击
2.000739574432373
"""
  • 违反的封闭原则,没有修改函数的调用方式,但是修改了函数源代码,所以这个方案舍弃掉

(2)方案二

def inside(group, s):
    print('欢迎来到王者荣耀')
    print(f'你出生在{group}方阵营')
    print(f'敌军还有{s}秒到达战场')
    time.sleep(s)
    print('全军出击')


start = time.time()
inside('红', 2)
end = time.time()
print(end - start)
"""
欢迎来到王者荣耀
你出生在红方阵营
敌军还有2秒到达战场
全军出击
2.000739574432373
"""
  • 这种方法没有修改源代码也没有修改函数的调用方式
  • 但是如果我们有100个函数都需要增加这个计算运行时间的功能
  • 就会出现很多重复的代码,这是一种十分low的行为
  • 所以这个方案也舍弃

(3)方案三

def inside(group, s):
    print('欢迎来到王者荣耀')
    print(f'你出生在{group}方阵营')
    print(f'敌军还有{s}秒到达战场')
    time.sleep(s)
    print('全军出击')


def wrapper():
    start = time.time()
    inside('红', 2)
    end = time.time()
    print(end - start)

wrapper()
  • 解决的方案二的代码冗余问题,也没有修改被装饰对象的源代码,同时还为其增加了新的功能
  • 但是被装饰对象的调用方式被修改了
  • 所以这个方案也得舍弃

(4)方案四

  • 暂且先不考虑如何解决不修改调用方式的问题
  • 看方案三的代码可以看到这个函数是一个死的函数
  • 如果被装饰对象的形参发生了修改,那就没有办法 了
def inside(group, s, z):
    print('欢迎来到王者荣耀')
    print(f'你出生在{group}方阵营')
    print(f'敌军还有{s}秒到达战场')
    time.sleep(s)
    print(f'{z}出击')


def wrapper(*args, **kwargs):
    start = time.time()
    inside(*args, **kwargs)
    end = time.time()
    print(end - start)


wrapper('红', 2, '炮车')

  • 通过*args和**kwargs,我们只需要按照被装饰对象的形参格式,随意传参就行了。
  • 可是这样一看,如果我们需要装饰其他的函数功能就无法达到效果了
  • 我们不能把被装饰对象写死,所以引出了方案五

(5)方案五

def inside(group, s, z):
    print('欢迎来到王者荣耀')
    print(f'你出生在{group}方阵营')
    print(f'敌军还有{s}秒到达战场')
    time.sleep(s)
    print(f'{z}出击')


def wrapper(*args, **kwargs):
    start = time.time()
    func(*args, **kwargs) ##这样子写会报红,应为wrapper没有接收到一个func
    end = time.time()
    print(end - start)


wrapper('红', 2, '炮车')

  • 思考解决办法
    1. 给函数传参
      • 直接通过参数传(wrapper的参数是原封不动的传给被装饰对象函数的,需要严格按照被装饰对象的形参,所以这个方法不可行)(False)
      • 通过闭包函数传(True)
def inside(group, s, z):
    print('欢迎来到王者荣耀')
    print(f'你出生在{group}方阵营')
    print(f'敌军还有{s}秒到达战场')
    time.sleep(s)
    print(f'{z}出击')


def outer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        func(*args, **kwargs)
        end = time.time()
        print(end - start)
    return wrapper # 注意不能加括号,加括号就变成调用了,我们只需要wrapper的内存地址


inside = outer(inside)
inside('红',2,'跑车')
  • 这样子就没有修改被装饰对象的源代码,且没有修改调用方式
  • 而且没有太多的代码冗余
  • 就完成了给被装饰对象添加功能

标签:group,inside,start,time,print,装饰,def
From: https://www.cnblogs.com/Hqqqq/p/17963188

相关文章

  • typescript实现一个最简的装饰器依赖注入
    装饰器依赖注入,元数据键是关键因此必须开启ts装饰器和ts元数据tsconfig.json"experimentalDecorators":true,//开启装饰器"emitDecoratorMetadata":true,//开启元数据并且安装reflect-metadata支持元数据编程全局入口倒入一次即可import"reflect-metadata";类型元数据:......
  • 【Python基础】函数进阶(匿名函数、装饰器、闭包等)
    简介函数进阶的使用,包括匿名函数、装饰器、闭包等匿名函数指函数是没有函数名称的,临时使用的微函数。使用lambda表达式来声明,语法格式如下:lambda[arg1[arg2,...,argn]]:表达式*[arg1,arg2,...,argn]为函数的参数列表,可有可无。*表达式:表示函数体,必须......
  • 闭包与装饰器
    闭包,又称闭包函数或者闭合函数,闭包函数就是指在一个嵌套函数里的内层函数,然后用内层函数来操纵外层函数的数据1.闭包函数点击查看代码defout_fun():#外层函数defin_fun():#内层函数print(10)returnin_fun#外层函数返回值,返回的是内层函数本......
  • C++设计模式05 —— 装饰模式
    装饰模式过度的使用继承使得派生的子类过多,代码重复度很高,复用性变差。实现加密文件流、加密网络流、加密内存流、缓冲文件流、缓冲网络流、缓冲内存流。如果我们创建一个流基类,然后创建文件流继承流基类,最后创建加密文件流继承文件流、创建缓冲文件流继承文件流。如果这......
  • 如何使用Python装饰器来修改函数
    在Python中,装饰器是一种强大的工具,它可以用来修改函数的行为,而无须对函数本身进行修改。装饰器提供了一种简洁、灵活的方式来扩展函数的功能,使代码更加模块化、可复用,并且能够减少重复的代码。装饰器的基本概念是将一个函数作为参数传递给另一个函数,并返回一个新的函数。这个新的函......
  • Python笔记三之闭包与装饰器
    本文首发于公众号:Hunter后端原文链接:Python笔记三之闭包与装饰器这一篇笔记介绍Python里面的装饰器。在介绍装饰器前,首先提出这样一个需求,我想统计某个函数的执行时间,假设这个函数如下:importtimedefadd(x,y):time.sleep(1)returnx+y想要统计add函数......
  • 软件体系结构与设计模式之装饰模式和外观模式
    一.单选题(共4题)(单选题)某公司欲开发一个图形控件库,要求可以在该图形控件库中方便地增加新的控件,而且可以动态地改变控件的外观或给控件增加新的行为,如可以为控件增加复杂的立体边框、增加控件的鼠标拖拽行为等。针对上述需求,使用()模式来进行设计最合适。A.适配器(Adap......
  • Python 装饰器
    Python装饰器python装饰器的本质是:仅以一个函数为参数,并返回一个函数。且看以下案例:defdecorator(f): print(f.__name__) returnf#1@decoratordeffun(): print("runfun")#2fun=decorator(fun)以上两种写法是等价的;装饰器函数会在被装饰的函数定义完成时......
  • 装饰器
    装饰器装饰代指为被装饰对象添加新的功能,器代指器具/工具,装饰器与被装饰的对象均可以是任意可调用对象。【一】装饰器的作用软件的设计应该遵循开放封闭原则,即对扩展是开放的,而对修改是封闭的。【二】装饰器的分类函数装饰器分为:无参装饰器和有参装饰器【三】无参装......
  • Decorator 装饰者模式简介与 C# 示例【结构型4】【设计模式来了_9】
    Decorator装饰者模式简介与C#示例【结构型4】【设计模式来了_9】 阅读目录〇、简介1、什么是装饰者模式2、优缺点和适用场景一、通过示例代码简单实现二、装饰者模式的结构三、相关模式回到顶部〇、简介1、什么是装饰者模式一句话解释:  通过继承统......