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 相关文章推荐
python使用Queue在多个子进程间交换数据的方法
Apr 18 Python
Python监控主机是否存活并以邮件报警
Sep 22 Python
Python输出各行命令详解
Feb 01 Python
Python常用字符串替换函数strip、replace及sub用法示例
May 21 Python
完美解决Python matplotlib绘图时汉字显示不正常的问题
Jan 29 Python
远程部署工具Fabric详解(支持Python3)
Jul 04 Python
matplotlib.pyplot.plot()参数使用详解
Jul 28 Python
python-地图可视化组件folium的操作
Dec 14 Python
删除pycharm鼠标右键快捷键打开项目的操作
Jan 16 Python
Pytest之测试命名规则的使用
Apr 16 Python
Python Django / Flask如何使用Elasticsearch
Apr 19 Python
代码复现python目标检测yolo3详解预测
May 06 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下通过系统信号量加锁方式获取递增序列ID
2009/09/25 PHP
PHP获取数组中单列值的方法
2017/06/10 PHP
PHP匿名函数(闭包函数)详解
2019/03/22 PHP
php-7.3.6 编译安装过程
2020/02/11 PHP
JS判断是否为数字,是否为整数,是否为浮点数的代码
2010/04/24 Javascript
JavaScript 开发规范要求(图文并茂)
2010/06/11 Javascript
JavaScript中函数声明优先于变量声明的实例分析
2012/03/01 Javascript
jQuery 自定义函数写法分享
2012/03/30 Javascript
JS原型对象通俗&quot;唱法&quot;
2012/12/27 Javascript
jquery html动态生成select标签出问题的解决方法
2013/11/20 Javascript
JS实现的4种数字千位符格式化方法分享
2015/03/02 Javascript
jQuery实现的背景动态变化导航菜单效果
2015/08/24 Javascript
jQuery插件zTree实现的多选树效果示例
2017/03/08 Javascript
js学使用setTimeout实现轮循动画
2017/07/17 Javascript
JS随机排序数组实现方法分析
2017/10/11 Javascript
ionic3实战教程之随机布局瀑布流的实现方法
2017/12/28 Javascript
JS实现带导航城市列表以及输入搜索功能
2018/01/04 Javascript
react中Suspense的使用详解
2019/09/01 Javascript
微信小程序(订阅消息)功能
2019/10/25 Javascript
python抓取某汽车网数据解析html存入excel示例
2013/12/04 Python
在Python中使用next()方法操作文件的教程
2015/05/24 Python
Django实现图片文字同时提交的方法
2015/05/26 Python
Python使用正则表达式过滤或替换HTML标签的方法详解
2017/09/25 Python
Python读取MRI并显示为灰度图像实例代码
2018/01/03 Python
Python实现的圆形绘制(画圆)示例
2018/01/31 Python
Python判断一个文件夹内哪些文件是图片的实例
2018/12/07 Python
Python搭建HTTP服务过程图解
2019/12/14 Python
用python解压分析jar包实例
2020/01/16 Python
解决Pycharm双击图标启动不了的问题(JetBrains全家桶通用)
2020/08/07 Python
使用Python pip怎么升级pip
2020/08/11 Python
基于CSS3实现的黑色个性导航菜单效果
2015/09/14 HTML / CSS
Daniel Wellington官方海外旗舰店:丹尼尔惠灵顿DW手表
2018/02/22 全球购物
小区的门卫岗位职责
2014/10/01 职场文书
门店店长岗位职责
2015/04/14 职场文书
六一儿童节主持开场白
2015/05/28 职场文书
成本低的5个创业项目:投资小、赚钱快
2019/08/20 职场文书