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中的两个内置模块介绍
Apr 05 Python
Python实现的Google IP 可用性检测脚本
Apr 23 Python
用Python实现web端用户登录和注册功能的教程
Apr 30 Python
python 实时遍历日志文件
Apr 12 Python
读取本地json文件,解析json(实例讲解)
Dec 06 Python
纯python实现机器学习之kNN算法示例
Mar 01 Python
Python错误处理操作示例
Jul 18 Python
Python字典创建 遍历 添加等实用基础操作技巧
Sep 13 Python
简单了解为什么python函数后有多个括号
Dec 19 Python
如何查看Django ORM执行的SQL语句的实现
Apr 20 Python
python百行代码自制电脑端网速悬浮窗的实现
May 12 Python
如何利用Python实现n*n螺旋矩阵
Jan 18 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
destoon二次开发入门示例
2014/06/20 PHP
thinkphp5.1框架模板赋值与变量输出示例
2020/05/25 PHP
JavaScript中Math对象使用说明
2008/01/16 Javascript
Jquery 获得服务器控件值的方法小结
2010/05/11 Javascript
Script的加载方法小结
2011/01/12 Javascript
让jQuery与其他JavaScript库并存避免冲突的方法
2013/12/23 Javascript
javascript类型转换示例
2014/04/29 Javascript
jQuery实现预加载图片的方法
2015/03/17 Javascript
jQuery 1.9.1源码分析系列(十五)动画处理之缓动动画核心Tween
2015/12/03 Javascript
浅析JS原型继承与类的继承
2016/04/07 Javascript
微信小程序 数据访问实例详解
2016/10/08 Javascript
利用JS判断鼠标移入元素的方向
2016/12/11 Javascript
使用 Vue.js 仿百度搜索框的实例代码
2017/05/09 Javascript
BootStrap daterangepicker 双日历控件
2017/06/02 Javascript
jQuery实现全选、反选和不选功能
2017/08/16 jQuery
JavaScript编程设计模式之构造器模式实例分析
2017/10/25 Javascript
解析vue路由异步组件和懒加载案例
2018/06/08 Javascript
javascript实现京东快递单号的查询效果
2020/11/30 Javascript
python 实现一个贴吧图片爬虫的示例
2017/10/12 Python
浅谈Matplotlib简介和pyplot的简单使用——文本标注和箭头
2018/01/09 Python
Python(TensorFlow框架)实现手写数字识别系统的方法
2018/05/29 Python
Python实现的登录验证系统完整案例【基于搭建的MVC框架】
2019/04/12 Python
Flask 上传自定义头像的实例详解
2020/01/09 Python
Selenium及python实现滚动操作多种方法
2020/07/21 Python
美国高品质个性化珠宝销售网站:Jewlr
2018/05/03 全球购物
数据库基础的一些面试题
2012/02/25 面试题
请说出这段代码执行后a和b的值分别是多少
2015/03/28 面试题
咖啡书吧创业计划书
2014/01/13 职场文书
给校长的建议书200字
2014/05/16 职场文书
医生辞职信范文
2015/03/02 职场文书
单位同意报考证明
2015/06/17 职场文书
《法国号》教学反思
2016/02/22 职场文书
使用CSS实现小三角边框原理解析
2021/11/07 HTML / CSS
mysql中varchar类型的日期进行比较、排序等操作的实现
2021/11/17 MySQL
MySQL 计算连续登录天数
2022/05/11 MySQL
解决spring.thymeleaf.cache=false不起作用的问题
2022/06/10 Java/Android