首页 > 编程语言 >python装饰器

python装饰器

时间:2022-10-18 14:12:49浏览次数:76  
标签:__ python hi func time print 装饰 def

 

参考:

https://www.runoob.com/w3cnote/python-func-decorators.html

https://www.jb51.net/article/240440.htm

用途:定义一个函数,来修饰之前老的代码,以便在不修改原代码的情况下增加新功能

关键原理:把函数作为参数,函数后面不加()就可以随意传递,加了()函数就会执行

一. 第一个装饰器例子

1.基本功能实现
def deco(func):
def inner():
  print("something before hi")
  func()
  print("something after hi")
return inner

def hi():
print("hi")

hi=deco(hi)
hi()

这正是 python 中装饰器做的事情!它们封装一个函数,并且用这样或者那样的方式来修改它的行为

2.现在用符号@来修改上面代码
def deco(func):
def inner():
  print("something before hi")
  func()
  print("something after hi")
return inner

@deco
def hi():
print("hi")

hi()
print(hi.__name__) //输出为inner

@deco其实就相当于hi=deco(hi)

不过现在最后一个行输出为inner, 我们想把它输出为hi,应该怎么做呢?

幸运的是Python提供给我们一个简单的函数来解决这个问题,那就是functools.wraps

3. functools.wraps改写
from functools import wraps

def deco(func):
@wraps(func)
def inner():
  print("something before hi")
  func()
  print("something after hi")
return inner

@deco
def hi():
print("hi")

hi()
print(hi.__name__) //输出为hi

@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。

 

二. 带参数的装饰器

from functools import wraps
import time

def delay_deco(delay=0):
 def deco(func):
   @wraps(func)
   def inner():
     print("something before hi")
     time1 = time.time()
     time.sleep(delay)
     time2 = time.time()
     func()
     print("something after hi")
     print("耗时:{:.8f}".format(time2-time1))
   return inner
 return deco

@delay_deco(2.0)
def hi():
 print("hi")

hi()
print(hi.__name__)

其实就是在原先的基础上,再加一层嵌套。上面代码实现延迟2秒执行,参数就是延迟的时间

 

三. 类装饰器

装饰器本身既可以是函数也可以是类,装饰的对象同样可以是函数也可以是类。

1. 最简单的例子
class Deco:
 def __init__(self, func):
   self._func = func

 def __call__(self, *args, **kwargs): #定义__call__函数,让类实例成为可调用对象
   print("类装饰器")
   return self._func(*args, **kwargs)

@Deco
def test():
 print("被装饰函数")

test()
例子2:根据例子1,稍微复杂点,被装饰的函数中添加参数
import time

class Deco:
 def __init__(self, func):
   self.func = func

 def __call__(self, *args, **kwargs):
   start = time.time()
   ret = self.func(*args, **kwargs)
   print(f'Time: {time.time()-start}')
   return ret

@Deco
def add(a,b):
 time.sleep(1)
 return a+b

print(add(3,4))

这个装饰器,相当于把一个装饰器变成了一个Deco类的对象,然后add被传入进了init中,保存为self.func

在后面调用add(3,4)的时候,实际上相当于调用了call这个函数,做了一个对象的调用,后面参数3和4就被传入到了call里面,然后依顺序运行了代码。

例子3:带参数的类装饰器
import time

class Deco:
 def __init__(self, prefix):
   self.prefix = prefix
   
 def __call__(self, func):
   def inner(*args, **kwargs):
     start = time.time()
     ret = func(*args, **kwargs)
     print(f'{self.prefix}: {time.time()-start}')
     return ret
   return inner

@Deco(prefix='current_time')
def add(a,b):
 time.sleep(1)
 return a+b

print(add(3,4))

我们把参数写入init函数中,相当于先实例化了一个Deco对象,call函数内做一个嵌套,类似于函数装饰器

标签:__,python,hi,func,time,print,装饰,def
From: https://www.cnblogs.com/regit/p/16802360.html

相关文章

  • python实现超级玛丽小游戏(动图演示+源码分享)
    下面给大家带来python实现超级玛丽小游戏的源码分享 效果演示:  1.基础设置(tools部分)这个部分设置马里奥以及游戏中蘑菇等怪的的移动设置。importosimpor......
  • OpenCV技巧 | 常用格式图片保存为透明背景图片(附Python源码)-教你轻松制作Logo
    导读本文主要介绍使用OpenCV将常用格式图片保存为透明背景图片的方法与实现代码。实现目标本文的目标有如下两个:①将常见格式[jpg/png/bmp]白色背景图片转换保存为透明背......
  • 实战 | 用Python和OpenCV搭建一个老人跌倒智能监测系统 (步骤 + 源码)
    导读本文将使用Python、OpenCV和MediaPipe搭建一个老人跌倒智能监测系统。(公众号:OpenCV与AI深度学习)背景介绍   老人监测系统是一种智能检测系统,可以检测老人是否躺在床......
  • Python中的多线程
    线程和进程线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线进程之间相互独立,但同一线程......
  • 【python】__init__.py文件到底是什么?
    __init__.py作用就是整个文件夹一个包来管理,每当有外部import的时候,就会自动执行里面的函数。1.概述在python中经常能看到__init__.py文件,似乎没什么用的样子,有的时候甚......
  • Python常用库
    一、python爬虫常用库Python在编写网络爬虫常用到库主要包括urllib、requests、lxml、fake-useragent、bs4(BeautifulSoup)、grab、pycurl、urllib3、httplib2、RoboBrow......
  • 「http代理」Python-Scrapy 代码样例(四)
    http代理使用提示1.http/https网页均可适用2.scrapy不是python原生库,需要安装才能使用:pipinstallscrapy3.在第一级tutorial目录下运行如下命令查看......
  • 「http代理」Python-Scrapy 代码样例(三)
    http代理使用提示1.http/https网页均可适用2.scrapy不是python原生库,需要安装才能使用:pipinstallscrapy3.在第一级tutorial目录下运行如下命令查看......
  • Python创建虚拟环境
    Python创建虚拟环境目录Python创建虚拟环境1命令行下1.1virtualenv1.2创建虚拟环境1.3激活/退出虚拟环境1.4删除虚拟环境1命令行下1.1virtualenvpip3installv......
  • python+clickhouse
    1.关于使用客户端能链接成功而使用代码无法访问clickhouse的问题clikchouse有两种链接方式:http端口默认为8123,tcp默认接口为9000使用客户端链接时用8123端口,而代码中就......