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 相关文章推荐
Eclipse + Python 的安装与配置流程
Mar 05 Python
在Python的Django框架中simple-todo工具的简单使用
May 30 Python
基于hashlib模块--加密(详解)
Jun 21 Python
Python编程pygal绘图实例之XY线
Dec 09 Python
Python实现的爬虫刷回复功能示例
Jun 07 Python
解决Django连接db遇到的问题
Aug 29 Python
python multiprocessing多进程变量共享与加锁的实现
Oct 02 Python
Pyqt5 关于流式布局和滚动条的综合使用示例代码
Mar 24 Python
Python函数必须先定义,后调用说明(函数调用函数例外)
Jun 02 Python
python 如何利用argparse解析命令行参数
Sep 11 Python
python中watchdog文件监控与检测上传功能
Oct 30 Python
pycharm实现猜数游戏
Dec 07 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
APMServ使用说明
2006/10/23 PHP
php中json_decode()和json_encode()的使用方法
2012/06/04 PHP
基于MySQL体系结构的分析
2013/05/02 PHP
PHP array_reverse() 函数原理及实例解析
2020/07/14 PHP
默认让页面的第一个控件选中的javascript代码
2009/12/26 Javascript
前端开发部分总结[兼容性、DOM操作、跨域等](持续更新)
2010/03/04 Javascript
关于JavaScript定义类和对象的几种方式
2010/11/09 Javascript
js DOM的学习笔记
2011/12/22 Javascript
js弹出的对话窗口永远保持居中显示
2012/12/15 Javascript
js实现简单的购物车有图有代码
2014/05/26 Javascript
JavaScript极简入门教程(三):数组
2014/10/25 Javascript
纯JS焦点图特效实例(可一个页面多用)
2016/12/07 Javascript
简单实现Vue的observer和watcher
2016/12/21 Javascript
JavaScript实现图像模糊化的方法实例
2017/01/15 Javascript
详解nodejs微信公众号开发——5.素材管理接口
2017/04/11 NodeJs
vue获取当前激活路由的方法
2018/03/17 Javascript
vue 使用v-for进行循环的实例代码详解
2020/02/19 Javascript
vue项目或网页上实现文字转换成语音播放功能
2020/06/09 Javascript
Python中的闭包实例详解
2014/08/29 Python
python类继承用法实例分析
2014/10/10 Python
Python对Excel按列值筛选并拆分表格到多个文件的代码
2019/11/05 Python
Python中lru_cache的使用和实现详解
2021/01/25 Python
HTML5实现WebSocket协议原理浅析
2014/07/07 HTML / CSS
比利时买床:Beter Bed
2017/12/06 全球购物
美国最受欢迎的度假目的地优惠套餐:BookVIP
2018/09/27 全球购物
中专生自我鉴定范文
2014/02/02 职场文书
淘宝店铺营销方案
2014/02/13 职场文书
学校出纳员岗位职责
2014/03/18 职场文书
员工安全承诺书
2014/05/22 职场文书
环境卫生倡议书
2014/08/29 职场文书
2014年重阳节老干部座谈会上的讲话稿
2014/09/25 职场文书
个人自我剖析材料
2014/09/30 职场文书
2016年“5.12”护士节致辞
2015/07/31 职场文书
mysql优化
2021/04/06 MySQL
用Python远程登陆服务器的步骤
2021/04/16 Python
MySQL实现字段分割一行转多行的示例代码
2022/07/07 MySQL