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的净值数据接口调用示例分享
Mar 15 Python
Python对象类型及其运算方法(详解)
Jul 05 Python
Python中的错误和异常处理简单操作示例【try-except用法】
Jul 25 Python
pandas series序列转化为星期几的实例
Apr 11 Python
python中aioysql(异步操作MySQL)的方法
Apr 11 Python
Python 经典算法100及解析(小结)
Sep 13 Python
DataFrame.to_excel多次写入不同Sheet的实例
Dec 02 Python
关于windows下Tensorflow和pytorch安装教程
Feb 04 Python
使用python3 实现插入数据到mysql
Mar 02 Python
Python发送邮件实现基础解析
Aug 14 Python
python基于win32api实现键盘输入
Dec 09 Python
Python Pandas list列表数据列拆分成多行的方法实现
Dec 14 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
真正的ZIP文件操作类(php)
2007/07/21 PHP
php中session过期时间设置及session回收机制介绍
2014/05/05 PHP
php中current、next与reset函数用法实例
2014/11/17 PHP
laravel5实现微信第三方登录功能
2018/12/06 PHP
JavaScript 应用类库代码
2008/06/02 Javascript
jQuery获取Select选择的Text和Value(详细汇总)
2013/01/25 Javascript
js 图片随机不定向浮动的实现代码
2013/07/02 Javascript
详解JS 比较两个Json对象的值是否相等的实例
2013/11/20 Javascript
jquery使用jquery.zclip插件复制对象的实例教程
2013/12/04 Javascript
Bootstrap源码解读按钮(5)
2016/12/23 Javascript
jquery滚动条插件slimScroll使用方法
2017/02/09 Javascript
利用策略模式与装饰模式扩展JavaScript表单验证功能
2017/02/14 Javascript
微信小程序 image组件binderror使用例子与js中的onerror区别
2017/02/15 Javascript
原生js实现密码输入框值的显示隐藏
2017/07/17 Javascript
Mobile Web开发基础之四--处理手机设备的横竖屏问题
2017/08/11 Javascript
jQuery 开发之EasyUI 添加数据的实例
2017/09/26 jQuery
基于JavaScript实现表格滚动分页
2017/11/22 Javascript
vue项目实战总结篇
2018/02/11 Javascript
详解vue组件开发脚手架
2018/06/15 Javascript
Vue中computed、methods与watch的区别总结
2019/04/10 Javascript
JS实现长图上下滚动效果
2020/03/19 Javascript
详解javascript void(0)
2020/07/13 Javascript
Bootstrap告警框(alert)实现弹出效果和短暂显示后上浮消失的示例代码
2020/08/27 Javascript
python生成器,可迭代对象,迭代器区别和联系
2018/02/04 Python
Python with用法:自动关闭文件进程
2019/07/10 Python
django多对多表的创建,级联删除及手动创建第三张表
2019/07/25 Python
Python的垃圾回收机制详解
2019/08/28 Python
PyInstaller的安装和使用的详细步骤
2020/06/02 Python
python Socket网络编程实现C/S模式和P2P
2020/06/22 Python
基于python实现操作redis及消息队列
2020/08/27 Python
提高EJB性能都有哪些技巧
2012/03/25 面试题
班组安全员工作职责
2014/02/01 职场文书
赔偿协议书怎么写
2015/01/28 职场文书
部门经理迟到检讨书
2015/02/16 职场文书
2015年林业工作总结
2015/05/14 职场文书
国王的演讲观后感
2015/06/03 职场文书