python装饰器的实现
说起装饰器我们可能已经很熟悉了(不了解的可以查看python基础学习——装饰器),随手就可以写一个简单的装饰器
def decorator(func):
def inner(*args, **kwargs):
# 执行函数前做点事
result = func(*args, **kwargs)
# 执行函数后干点啥
return result
return inner
但是装饰器的实现可不是只有这一种,请看下面
通过类来实现
上面写的装饰器是由函数的方式实现的,但我们也可以用类的方式写一个同样的装饰器,还记得call方法吗
class decorator:
def __init__(self,func):
self.func = func
def __call__(self, *args, **kwargs):
# 执行函数前做点事
result = self.func(*args, **kwargs)
# 执行函数后干点啥
return result
比如有一个add()函数被装饰,其实相当于add = decorator(add),那么decorator(add)就是这个类的实例, 执行add(a,b)的时候就是执行call方法了
参数化的装饰器
在装饰器中,我们在被装饰函数执行前会做一些事,在被装饰函数执行后可能也会做一些事,可是按照上面的写法,这些事情都是固定写好的,可不可以让这些动作会自定义的做些区别变化,那么参数化的装饰器能够满足这个要求
def decorator(what_i_say='我什么也没说'):
def actual_decorator(func):
def inner(*args, **kwargs):
# 执行函数前做点事
print(what_i_say)
result = func(*args, **kwargs)
# 执行函数后干点啥
return result
return inner
return actual_decorator
@decorator('我要做一次加法')
def add(a, b):
return a + b
print(add(3, 9))
有了这个参数化装饰器,我们就可以在装饰函数时将参数写在括号内,也就是传入参数(这里我传的是字符串,其实没啥意义,只是为了简单表示参数)
但是我们看到这个装饰器的实现中出现了三次def,之前的不都是出现两次吗,这次怎么出现了3次?它是怎么执行的
其实稍微想一下就想通了,还是按照装饰的过程来
之前是add = decorator(add),这次就把decorator换成decorator(‘我要做一次加法’),add = decorator(‘我要做一次加法’)(add),由于函数是一等对象,所以decorator(‘我要做一次加法’)就是装饰器中第一次返回的actual_decorator,由于闭包的特性,传递的参数绑定到了内部函数中,所以decorator执行完后,传入的’我要做一次加法’还是可以打印出来。
所以这个参数化的装饰器和普通的装饰器装饰的过程是一样的。
保存函数元数据的装饰器
在使用装饰器后一段时间,可能有一天我们会突然发现一点不对劲的地方,比如我们打印被装饰的函数的时候
print(add)
#<function decorator.<locals>.actual_decorator.<locals>.inner at 0x00000211E632CB70>
咦,不对啊,怎么它的名字不是add而是decorator..actual_decorator..inner这个玩意。我们仔细一读想起来了,这是被装饰器装饰了的那个函数,所以它把装饰器里的那个给打印出来了。可是把这个玩意打印出来干嘛呀,我要原来的函数名,有没有什么办法啊,办法当然有,如下
from functools import wraps
def decorator(what_i_say):
def actual_decorator(func):
@wraps(func)
def inner(*args, **kwargs):
# 执行函数前做点事
print(what_i_say)
result = func(*args, **kwargs)
# 执行函数后干点啥
return result
return inner
return actual_decorator
我们从functools模块中引入了wraps()装饰器,用它来装饰装饰器中的inner函数,这样再次使用这个装饰器去装饰函数,它的元数据就保留下来了
@decorator('我要做一次加法')
def add(a, b):
return a + b
print(add)
# <function add at 0x000001F5DEE966A8>
python装饰器的实现的更多相关文章
- 关于python装饰器
关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...
- python装饰器通俗易懂的解释!
1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...
- Python 装饰器学习
Python装饰器学习(九步入门) 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...
- python 装饰器修改调整函数参数
简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...
- python 装饰器学习(decorator)
最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...
- Python装饰器详解
python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...
- 关于python装饰器(Decorators)最底层理解的一句话
一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...
- Python装饰器由浅入深
装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...
- Python装饰器与面向切面编程
今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...
- python装饰器方法
前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看dja ...
随机推荐
- 配置redis
配置Redis 配置相关redis.conf bind 127.0.0.1 注释掉 否则其它远程计算机无 ...
- Web渗透:PHP字符编码绕过漏洞总结
其实这东西国内少数黑客早已知道,只不过没有共享公布而已.有些人是不愿共享,宁愿烂在地里,另外的一些则是用来牟利. 该漏洞最早2006年被国外用来讨论数据库字符集设为GBK时,0xbf27本身不是一个有 ...
- linux下配置nginx负载均衡例子
准备2台虚拟机: 分别在两个虚拟机上安装tomcat,并在服务器A安装nginx,其中nginx端口设置为了 70. 服务器A的tomcat安装目录: 服务器B的tomcat安装目录: 服务器A的ng ...
- Android_性能优化转载
胡凯 RSS Blog Archives Android Training in Chinese About Android性能优化典范 JAN 17TH, 2015 | COMMENTS 2015年 ...
- [教程向]__在IDEA中使用git+github实现代码的版本控制
前言 在前面,我们对git与github有了一个简单的了解,了解到版本控制的必要性,和github远程代码仓库的一些作用.那么我们如何在IDEA重实现代码的版本控制呢. 前提 首先你要安装有git,注 ...
- 829. 连续整数求和-leetcode
题目:给定一个正整数 N,试求有多少组连续正整数满足所有数字之和为 N? 示例 1: 输入: 5 输出: 2 解释: 5 = 5 = 2 + 3,共有两组连续整数([5],[2,3])求和后为 5. ...
- PetaPoco在ASP.NET Core 2.2中使用注入方式访问数据库
.Net Core中一个特别重要的特性就是依赖注入功能,那么我们在使用PetaPoco的时候是否也可以使用依赖注入特性呢? 回答当然是可以的啦.使用方法(两种注入方式)如下 services.AddS ...
- ES启动报错之引导检测失败
[--16T18::,][ERROR][o.e.b.Bootstrap ] [node-] node validation exception [] bootstrap checks failed [ ...
- java高级工程师开放面试题集<一>
临近年关,不少人蠢蠢欲动,有童鞋问我java后端面试会面试什么? 作为一个java后端老鸟,跌打滚爬多次被面试和面试别人,总结了一些经验,希望对大家有所帮助. 特别说明,仅仅针对工作两年以上的java ...
- 微信小程序 - 入门指引
稍微整了整微信小程序,还是有不少问题的,做个小总结吧 和以往一样,本次项目也放到了 Github 中,欢迎围观 star ~ 一.微信公众平台 - 小程序后台 1.申请小程序账号 官网注册 注册时所用 ...