Python的装饰器用法学习笔记


Posted in Python onJune 24, 2016

在python中常看到在定义函数是使用@func. 这就是装饰器, 装饰器是把一个函数作为参数的函数,常常用于扩展已有函数,即不改变当前函数状态下增加功能.

def run():
  print "I'm run."

我有这么一个函数, 我想知道这个函数什么时候开始什么时候结束. 我应该这么写

def run():
  print time.ctime()
  print "I'm run."
  print time.ctime()

但是如果不允许修改函数的话就需要装饰器了

def count(func):
  def wrapper():
    print time.ctime()
    ret = func()
    print time.ctime()
    return ret
  return wrapper

@count
def run():
  print "I'm run."

      # print '2015-4-10'

eg:

def now():
  print '2015-4-10'
f = now
f()

 

函数有一个__name__ 对象 可通过 dir(func) func为定义的函数名

now.__name__    # print 'now'
f.__name__     # print 'now'

print f       # print '<function now at 0x000000000213A908>'
print now      # print '<function now at 0x000000000213A908>'

我们通过装饰器打印log日志

def log(func):
  def wrapper(*args, **kwargs):
    print "call %s()" % func.__name__
    return func(*args, **kwargs)
  return wrapper

@log
def now():
  print '2015-4-10'

now()        # print 'call now()'

其实装饰器修饰函数相当于, now = log(now) 也就是装饰器函数把被修饰的函数当参数后赋给同名的变量

functools.wraps 函数

当我们使用了装饰器后now的__name__值发生了改变

# 没有使用前
now.__name__    # print 'now'
# 使用后
now.__name__    # print 'wrapper'

当我们使用装饰器前,now.__name__使用的是当前now函数,但使用后 now这个函数其实是 log(now) 也就是log函数的返回值也就是被包裹的wrapper. 解决方法是functools.wraps函数.

装饰闭包, 使用前得调用 import functools

def log(func):
  @functools.wraps(func)
  def wrapper(*args, **kwargs):
    ...

带参数的装饰器

如果decorator需要传入参数, 那就需要在写一个返回decorator的高阶函数. 写出来更复杂.

def login(level):
  def _deco(func):
    def wrapper(*args, **kwargs):
      if level >= 5:
        print '用户 VIP 等级 %d' % int(level-5)
      else:
        print '用户 ?潘 等级 %d' % abs(level-5)
      return func(*args, **kwargs)
    return wrapper
  return _deco

@login(5)
def user(username):
  print 'welcome, %s' % username

# 用户vip 等级0
# welcome, mink
user('mink')

带参数的decorator等于func = 装饰器函数(装饰器参数)(func)

装饰器类

通过类的__call__可以想使用函数一样使用类

class A(object):
  def __init__(self, func):
    self.func = func

  def __call__(self):
    return self.func() ** 2

@A
def foo():
  return 10

print foo()   # print 100
Python 相关文章推荐
python网络编程学习笔记(二):socket建立网络客户端
Jun 09 Python
python实现下载整个ftp目录的方法
Jan 17 Python
python数据类型判断type与isinstance的区别实例解析
Oct 31 Python
Python实现KNN邻近算法
Jan 28 Python
把csv文件转化为数组及数组的切片方法
Jul 04 Python
python 遍历列表提取下标和值的实例
Dec 25 Python
python监控进程状态,记录重启时间及进程号的实例
Jul 15 Python
python爬虫模拟浏览器访问-User-Agent过程解析
Dec 28 Python
PYQT5 vscode联合操作qtdesigner的方法
Mar 24 Python
Django执行源生mysql语句实现过程解析
Nov 12 Python
python3从网络摄像机解析mjpeg http流的示例
Nov 13 Python
python opencv旋转图片的使用方法
Jun 04 Python
Python的网络编程库Gevent的安装及使用技巧
Jun 24 #Python
深入解析Python编程中super关键字的用法
Jun 24 #Python
深入了解Python数据类型之列表
Jun 24 #Python
Python实现信用卡系统(支持购物、转账、存取钱)
Jun 24 #Python
Python提取Linux内核源代码的目录结构实现方法
Jun 24 #Python
Linux上安装Python的PIL和Pillow库处理图片的实例教程
Jun 23 #Python
尝试用最短的Python代码来实现服务器和代理服务器
Jun 23 #Python
You might like
php完全过滤HTML,JS,CSS等标签
2009/01/16 PHP
php无限极分类实现的两种解决方法
2013/04/28 PHP
php注册和登录界面的实现案例(推荐)
2016/10/24 PHP
jQuery使用手册之一
2007/03/24 Javascript
js最简单的拖拽效果实现代码
2010/09/24 Javascript
js replace正则表达式应用案例讲解
2013/01/17 Javascript
前端开发过程中浏览器版本的两种判定方法
2013/10/30 Javascript
JavaScript/Js脚本处理html元素的自定义属性解析(亲测兼容Firefox与IE)
2013/11/25 Javascript
了不起的node.js读书笔记之mongodb数据库交互
2014/12/22 Javascript
jQuery随机密码生成的方法
2015/03/09 Javascript
JS简单实现数组去重的方法示例
2017/03/27 Javascript
利用PM2部署node.js项目的方法教程
2017/05/10 Javascript
jQuery 循环遍历改变a标签的href(实例讲解)
2017/07/12 jQuery
React/Redux应用使用Async/Await的方法
2017/11/16 Javascript
Vue 过滤器filters及基本用法
2017/12/26 Javascript
基于React+Redux的SSR实现方法
2018/07/03 Javascript
vue实例中data使用return包裹的方法
2018/08/27 Javascript
浏览器事件循环与vue nextTicket的实现
2019/04/16 Javascript
layui异步加载table表中某一列数据的例子
2019/09/16 Javascript
python检测主机的连通性并记录到文件的实例
2018/06/21 Python
Python实现简易过滤删除数字的方法小结
2019/01/09 Python
python读取raw binary图片并提取统计信息的实例
2020/01/09 Python
Pytorch 实现计算分类器准确率(总分类及子分类)
2020/01/18 Python
浅谈python opencv对图像颜色通道进行加减操作溢出
2020/06/03 Python
纯CSS实现聊天框小尖角、气泡效果
2014/04/04 HTML / CSS
深入理解HTML5定时器requestAnimationFrame的使用
2018/12/12 HTML / CSS
*p++ 自增p 还是p所指向的变量
2016/07/16 面试题
本科毕业生的求职信范文
2013/11/20 职场文书
2014年小学生迎国庆65周年演讲稿
2014/09/27 职场文书
2014年综治维稳工作总结
2014/11/17 职场文书
2014年领导班子工作总结
2014/12/11 职场文书
先进个人材料怎么写
2014/12/30 职场文书
民间借贷纠纷案件代理词
2015/05/26 职场文书
干部考核工作总结2015
2015/07/24 职场文书
关于golang高并发的实现与注意事项说明
2021/05/08 Golang
MySQL 8.0 驱动与阿里druid版本兼容问题解决
2021/07/01 MySQL