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 httplib,smtplib使用方法
Sep 06 Python
python使用cookielib库示例分享
Mar 03 Python
Python调用C语言开发的共享库方法实例
Mar 18 Python
python PIL模块与随机生成中文验证码
Feb 27 Python
Python + selenium自动化环境搭建的完整步骤
May 19 Python
Python学习笔记之视频人脸检测识别实例教程
Mar 06 Python
python tkinter canvas 显示图片的示例
Jun 13 Python
python+Django+pycharm+mysql 搭建首个web项目详解
Nov 29 Python
Python退出时强制运行一段代码的实现方法
Apr 29 Python
浅析Python 抽象工厂模式的优缺点
Jul 13 Python
全网最详细的PyCharm+Anaconda的安装过程图解
Jan 25 Python
Django基础CBV装饰器和中间件
Mar 22 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
星际争霸任务指南——虫族
2020/03/04 星际争霸
php为什么选mysql作为数据库? Mysql 创建用户方法
2007/07/02 PHP
php实现购物车功能(下)
2016/01/05 PHP
phpstudy默认不支持64位php的解决方法
2017/02/20 PHP
php实现的redis缓存类定义与使用方法示例
2017/08/09 PHP
PHP查找一列有序数组是否包含某值的方法
2020/02/07 PHP
JS 巧妙获取剪贴板数据 Excel数据的粘贴
2009/07/09 Javascript
仅img元素创建后不添加到文档中会执行onload事件的解决方法
2011/07/31 Javascript
Jquery阻止事件冒泡 event.stopPropagation
2011/12/11 Javascript
jQuery学习笔记 操作jQuery对象 属性处理
2012/09/19 Javascript
js图片自动轮播代码分享(js图片轮播)
2014/05/06 Javascript
jQuery获取上传文件的名称的正则表达式
2015/05/21 Javascript
跟我学习javascript的函数调用和构造函数调用
2015/11/16 Javascript
Angular.js中$resource高大上的数据交互详解
2017/07/30 Javascript
JavaScript上传文件时不用刷新页面方法总结(推荐)
2017/08/15 Javascript
vue.js使用watch监听路由变化的方法
2018/07/08 Javascript
vue2.0中set添加属性后视图不能更新的解决办法
2019/02/22 Javascript
django数据库migrate失败的解决方法解析
2018/02/08 Python
python绘制简单彩虹图
2018/11/19 Python
Python使用get_text()方法从大段html中提取文本的实例
2019/08/27 Python
redis数据库及与python交互用法简单示例
2019/11/01 Python
pandas中ix的使用详细讲解
2020/03/09 Python
python实现将两个文件夹合并至另一个文件夹(制作数据集)
2020/04/03 Python
CSS3中新增的对文本和字体的设置
2020/02/03 HTML / CSS
canvas 下载二维码和图片加水印的方法
2018/03/21 HTML / CSS
伦敦高达60%折扣的钻石珠宝商:Purely Diamonds
2018/06/24 全球购物
The North Face官方旗舰店:美国著名户外品牌
2020/09/28 全球购物
一个C/C++编程面试题
2013/11/10 面试题
优秀大学生职业生涯规划书
2014/02/27 职场文书
企业形象策划方案
2014/05/29 职场文书
比赛口号大全
2014/06/10 职场文书
师德师风个人总结
2015/02/06 职场文书
会议营销主持词
2015/07/03 职场文书
治理商业贿赂工作总结
2015/08/10 职场文书
在CSS中映射鼠标位置并实现通过鼠标移动控制页面元素效果(实例代码)
2021/04/22 HTML / CSS
Vertica集成Apache Hudi重磅使用指南
2022/03/31 Servers