Python装饰器知识点补充


Posted in Python onMay 28, 2018

首先回顾一下关于Python装饰器以及装饰器模式

补全

根据Java实现装饰器模式的,我们可以写下面一段代码:

import logging


def use_logging(func):
 logging.warn("%s is running" % func.__name__)
 return func

def foo():
 print('i am foo')

foo = use_logging(foo)

foo() # 调用

这个实现对于上篇文章中提到的Java使用装饰器。上面也是一个装饰器,实现最简单的一个增加函数日志的功能,但是如果这个额外功能是要去检测传入的参数时,这时上面的就不行了。这时12步轻松搞定python装饰器中的例子还是精妙的。

# 装饰器
def wrapper(func):
 def checker(a, b): # 1
  if a.x < 0 or a.y < 0:
   a = Coordinate(a.x if a.x > 0 else 0, a.y if a.y > 0 else 0)
  if b.x < 0 or b.y < 0:
   b = Coordinate(b.x if b.x > 0 else 0, b.y if b.y > 0 else 0)
  ret = func(a, b)
  if ret.x < 0 or ret.y < 0:
   ret = Coordinate(ret.x if ret.x > 0 else 0, ret.y if ret.y > 0 else 0)
  return ret
 return checker


# 原函数
def add(a, b):
 return Coordinate(a.x + b.x, a.y + b.y)

# 使用装饰 
add = wrapper(add)

细心你会发现,装饰器函数的参数就是传入的原函数,而内部函数的参数跟原函数一模一样,最外层返回的是内部函数的引用,内部函数返回的是传入参数的引用调用的结果

这里用到了函数作为参数特性,当然还有些闭包的知识,具体请看 上面提到的博客链接,真的讲的不错。

而上篇说到的Python装饰 特性就是这个神奇的语法糖了,可以这样使用

# 原函数
@wrapper
def add(a, b):
 return Coordinate(a.x + b.x, a.y + b.y)

带参数的装饰器

如果要实现一个带参数的装饰器,那要怎么写呢

def time_diff(s):
 def decorator(func):
  def wrapper(*args, **kwargs):
   start_time = time.time()
   res = func(*args, **kwargs)
   end_time = time.time()
   print("[%s]执行程序所用时间: %s" % (s, end_time - start_time))
   return res
  return wrapper
 return decorator
 
@time_diff("polynomial_1")
def polynomial_1(n, x):
 res = 0
 for i in range(n):
  res += i*pow(x, i)
 return res

调用并执行输出结果:

print(polynomial_1(1, 5))

[duoxiangshi_1]执行程序所用时间: 4.76837158203125e-06
0

带参数的装饰器需要在不带参数装饰器外再定义一层函数,最外层函数的返回值是第二层函数的引用。

总结:多些多练,用于实际中,才能更加熟练。最近学数据结构与算法,写些装饰器用来看程序执行时间,真是再方便不过了!

Python 相关文章推荐
Flask框架学习笔记(一)安装篇(windows安装与centos安装)
Jun 25 Python
举例讲解Python的lambda语句声明匿名函数的用法
Jul 01 Python
关于Python面向对象编程的知识点总结
Feb 14 Python
Python OS模块实例详解
Apr 15 Python
使用python画社交网络图实例代码
Jul 10 Python
python 环境搭建 及python-3.4.4的下载和安装过程
Jul 20 Python
python、Matlab求定积分的实现
Nov 20 Python
python数字类型math库原理解析
Mar 02 Python
浅谈keras使用中val_acc和acc值不同步的思考
Jun 18 Python
python语音识别指南终极版(有这一篇足矣)
Sep 09 Python
python 利用matplotlib在3D空间绘制二次抛物面的案例
Feb 06 Python
python实现web邮箱扫描的示例(附源码)
Mar 30 Python
更换Django默认的模板引擎为jinja2的实现方法
May 28 #Python
django manage.py扩展自定义命令方法
May 27 #Python
python实现windows下文件备份脚本
May 27 #Python
django 解决manage.py migrate无效的问题
May 27 #Python
关于django 数据库迁移(migrate)应该知道的一些事
May 27 #Python
解决Django migrate No changes detected 不能创建表的问题
May 27 #Python
django 在原有表格添加或删除字段的实例
May 27 #Python
You might like
php中计算未知长度的字符串哪个字符出现的次数最多的代码
2012/08/14 PHP
thinkPHP5.0框架环境变量配置方法
2017/03/17 PHP
Laravel 5使用Laravel Excel实现Excel/CSV文件导入导出的功能详解
2017/10/11 PHP
php实现构建排除当前元素的乘积数组方法
2018/10/06 PHP
解决laravel(5.5)访问public报错的问题
2019/10/12 PHP
对javascript的一点点认识总结《javascript高级程序设计》读书笔记
2011/11/30 Javascript
node.js中的fs.chownSync方法使用说明
2014/12/16 Javascript
使用jquery菜单插件HoverTree仿京东无限级菜单
2014/12/18 Javascript
JavaScript数组对象赋值用法实例
2015/08/04 Javascript
JS实现的最简Table选项卡效果
2015/10/14 Javascript
微信小程序 跳转传参数与传对象详解及实例代码
2017/03/14 Javascript
微信小程序tabBar模板用法实例分析【附demo源码下载】
2017/11/28 Javascript
vue移动端轻量级的轮播组件实现代码
2018/07/12 Javascript
React Native开发封装Toast与加载Loading组件示例
2018/09/08 Javascript
vue踩坑记录之数组定义和赋值问题
2019/03/20 Javascript
jquery实现的分页显示功能示例
2019/08/23 jQuery
layui实现鼠标移动到单元格上显示数据的方法
2019/09/11 Javascript
Vue.js暴露方法给WebView的使用操作
2020/09/07 Javascript
跟老齐学Python之编写类之二方法
2014/10/11 Python
python根据出生日期获得年龄的方法
2015/03/31 Python
Python3处理文件中每个词的方法
2015/05/22 Python
python中的字典使用分享
2016/07/31 Python
详解python调度框架APScheduler使用
2017/03/28 Python
python使用socket创建tcp服务器和客户端
2018/04/12 Python
Python中的函数式编程:不可变的数据结构
2018/10/08 Python
python中将zip压缩包转为gz.tar的方法
2018/10/18 Python
python:解析requests返回的response(json格式)说明
2020/04/30 Python
园长自我鉴定
2013/10/06 职场文书
销售演讲稿范文
2014/01/08 职场文书
销售辞职报告范文
2014/01/12 职场文书
幼儿园实习生辞职信
2014/01/20 职场文书
2014年大学庆元旦迎新年活动方案
2014/03/09 职场文书
2014年征兵标语
2014/06/20 职场文书
2015年科协工作总结
2015/05/19 职场文书
html2 canvas svg不能识别的解决方案
2021/06/03 HTML / CSS
在Java中Collection的一些常用方法总结
2021/06/13 Java/Android