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里大整数相乘相关技巧指南
Sep 12 Python
python机器学习理论与实战(一)K近邻法
Jan 28 Python
python中多层嵌套列表的拆分方法
Jul 02 Python
Python做智能家居温湿度报警系统
Sep 25 Python
python sort、sort_index方法代码实例
Mar 28 Python
如何为Python终端提供持久性历史记录
Sep 03 Python
python实现连续变量最优分箱详解--CART算法
Nov 22 Python
Python多线程获取返回值代码实例
Feb 17 Python
Python参数传递对象的引用原理解析
May 22 Python
如何在keras中添加自己的优化器(如adam等)
Jun 19 Python
Python基于callable函数检测对象是否可被调用
Oct 16 Python
Python实现制作销售数据可视化看板详解
Nov 27 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中通过ADO调用Asscess数据库和COM程序
2006/10/09 PHP
PHP抽象类 介绍
2012/06/13 PHP
laravel与thinkphp之间的区别与优缺点
2021/03/02 PHP
javascript 日历提醒系统( 兼容所有浏览器 )
2009/04/07 Javascript
利用jQuery的$.event.fix函数统一浏览器event事件处理
2009/12/21 Javascript
20个非常有用的PHP类库 加速php开发
2010/01/15 Javascript
js中判断数字\字母\中文的正则表达式 (实例)
2012/06/29 Javascript
动态读取JSON解析键值对的方法
2014/06/03 Javascript
JavaScript中的style.cssText使用教程
2014/11/06 Javascript
使用javascript实现简单的选项卡切换
2015/01/09 Javascript
Bootstrap 布局组件(全)
2016/07/18 Javascript
关于微信中a链接无法跳转问题
2016/08/02 Javascript
JavaScript 中 apply 、call 的详解
2017/03/21 Javascript
JS简单验证上传文件类型的方法
2017/04/17 Javascript
JavaScript实现的数字与字符串转换功能示例
2017/08/23 Javascript
JS使用Date对象实时显示当前系统时间简单示例
2018/08/23 Javascript
小程序实现列表删除功能
2018/10/30 Javascript
详解无限滚动插件vue-infinite-scroll源码解析
2019/05/12 Javascript
Vue项目打包部署到iis服务器的配置方法
2019/10/14 Javascript
详解vue 中 scoped 样式作用域的规则
2020/09/14 Javascript
[53:44]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Magma BO3 第一场 1月31日
2021/03/11 DOTA
Python标准库之随机数 (math包、random包)介绍
2014/11/25 Python
python中pygame针对游戏窗口的显示方法实例分析(附源码)
2015/11/11 Python
《Python学习手册》学习总结
2018/01/17 Python
Python cookbook(数据结构与算法)将序列分解为单独变量的方法
2018/02/13 Python
python实现多进程通信实例分析
2019/09/01 Python
Python安装tar.gz格式文件方法详解
2020/01/19 Python
Python实现PS滤镜中的USM锐化效果
2020/12/04 Python
THE OUTNET美国官网:国际设计师品牌折扣网站
2017/03/07 全球购物
领先的荷兰线上超市:荷兰之家Holland at Home(支持中文)
2021/01/21 全球购物
德国二手设计师时装和复古时装跳蚤市场:Mädchenflohmarkt
2020/11/09 全球购物
超市业务员岗位职责
2013/12/05 职场文书
家庭教育的心得体会
2014/09/01 职场文书
2014党委书记四风对照检查材料思想汇报
2014/09/21 职场文书
党员考试作弊检讨书1000字
2015/02/16 职场文书
2015年汽车销售经理工作总结
2015/04/27 职场文书