九步学会Python装饰器


Posted in Python onMay 09, 2015

本文实例讲述了Python装饰器。分享给大家供大家参考。具体分析如下:

这是在Python学习小组上介绍的内容,现学现卖、多练习是好的学习方式。
第一步:最简单的函数,准备附加额外功能

# -*- coding:gbk -*-
'''示例1: 最简单的函数,表示调用了两次'''
def myfunc():
  print("myfunc() called.")
myfunc()
myfunc()

第二步:使用装饰函数在函数执行前和执行后分别附加额外功能

# -*- coding:gbk -*-
'''示例2: 替换函数(装饰)
装饰函数的参数是被装饰的函数对象,返回原函数对象
装饰的实质语句: myfunc = deco(myfunc)'''
 
def deco(func):
  print("before myfunc() called.")
  func()
  print(" after myfunc() called.")
  return func
def myfunc():
  print(" myfunc() called.")
myfunc = deco(myfunc)
myfunc()
myfunc()

第三步:使用语法糖@来装饰函数

# -*- coding:gbk -*-
'''示例3: 使用语法糖@来装饰函数,相当于“myfunc = deco(myfunc)”
但发现新函数只在第一次被调用,且原函数多调用了一次'''
 
def deco(func):
  print("before myfunc() called.")
  func()
  print(" after myfunc() called.")
  return func
@deco
def myfunc():
  print(" myfunc() called.")
myfunc()
myfunc()

第四步:使用内嵌包装函数来确保每次新函数都被调用

# -*- coding:gbk -*-
'''示例4: 使用内嵌包装函数来确保每次新函数都被调用,
内嵌包装函数的形参和返回值与原函数相同,
装饰函数返回内嵌包装函数对象'''
 
def deco(func):
  def _deco():
    print("before myfunc() called.")
    func()
    print(" after myfunc() called.")
    # 不需要返回func,实际上应返回原函数的返回值
  return _deco
@deco
def myfunc():
  print(" myfunc() called.")
  return 'ok'
myfunc()
myfunc()

第五步:对带参数的函数进行装饰

# -*- coding:gbk -*-
'''示例5: 对带参数的函数进行装饰,
内嵌包装函数的形参和返回值与原函数相同,
装饰函数返回内嵌包装函数对象'''
def deco(func):
  def _deco(a, b):
    print("before myfunc() called.")
    ret = func(a, b)
    print(" after myfunc() called. result: %s" % ret)
    return ret
  return _deco
@deco
def myfunc(a, b):
  print(" myfunc(%s,%s) called." % (a, b))
  return a + b
myfunc(1, 2)
myfunc(3, 4)

第六步:对参数数量不确定的函数进行装饰

# -*- coding:gbk -*-
'''示例6: 对参数数量不确定的函数进行装饰,
参数用(*args, **kwargs),自动适应变参和命名参数'''
def deco(func):
  def _deco(*args, **kwargs):
    print("before %s called." % func.__name__)
    ret = func(*args, **kwargs)
    print(" after %s called. result: %s" % (func.__name__, ret))
    return ret
  return _deco
@deco
def myfunc(a, b):
  print(" myfunc(%s,%s) called." % (a, b))
  return a+b
@deco
def myfunc2(a, b, c):
  print(" myfunc2(%s,%s,%s) called." % (a, b, c))
  return a+b+c
myfunc(1, 2)
myfunc(3, 4)
myfunc2(1, 2, 3)
myfunc2(3, 4, 5)

第七步:让装饰器带参数

# -*- coding:gbk -*-
'''示例7: 在示例4的基础上,让装饰器带参数,
和上一示例相比在外层多了一层包装。
装饰函数名实际上应更有意义些'''
def deco(arg):
  def _deco(func):
    def __deco():
      print("before %s called [%s]." % (func.__name__, arg))
      func()
      print(" after %s called [%s]." % (func.__name__, arg))
    return __deco
  return _deco
@deco("mymodule")
def myfunc():
  print(" myfunc() called.")
@deco("module2")
def myfunc2():
  print(" myfunc2() called.")
myfunc()
myfunc2()

第八步:让装饰器带 类 参数

# -*- coding:gbk -*-
'''示例8: 装饰器带类参数'''
class locker:
  def __init__(self):
    print("locker.__init__() should be not called.")
  @staticmethod
  def acquire():
    print("locker.acquire() called.(这是静态方法)")
  @staticmethod
  def release():
    print(" locker.release() called.(不需要对象实例)")
def deco(cls):
  '''cls 必须实现acquire和release静态方法'''
  def _deco(func):
    def __deco():
      print("before %s called [%s]." % (func.__name__, cls))
      cls.acquire()
      try:
        return func()
      finally:
        cls.release()
    return __deco
  return _deco
@deco(locker)
def myfunc():
  print(" myfunc() called.")
myfunc()
myfunc()

第九步:装饰器带类参数,并分拆公共类到其他py文件中,同时演示了对一个函数应用多个装饰器

# -*- coding:gbk -*-
'''mylocker.py: 公共类 for 示例9.py'''
class mylocker:
  def __init__(self):
    print("mylocker.__init__() called.")
  @staticmethod
  def acquire():
    print("mylocker.acquire() called.")
  @staticmethod
  def unlock():
    print(" mylocker.unlock() called.")
class lockerex(mylocker):
  @staticmethod
  def acquire():
    print("lockerex.acquire() called.")
  @staticmethod
  def unlock():
    print(" lockerex.unlock() called.")
def lockhelper(cls):
  '''cls 必须实现acquire和release静态方法'''
  def _deco(func):
    def __deco(*args, **kwargs):
      print("before %s called." % func.__name__)
      cls.acquire()
      try:
        return func(*args, **kwargs)
      finally:
        cls.unlock()
    return __deco
  return _deco
# -*- coding:gbk -*-
'''示例9: 装饰器带类参数,并分拆公共类到其他py文件中
同时演示了对一个函数应用多个装饰器'''
from mylocker import *
class example:
  @lockhelper(mylocker)
  def myfunc(self):
    print(" myfunc() called.")
 
  @lockhelper(mylocker)
  @lockhelper(lockerex)
  def myfunc2(self, a, b):
    print(" myfunc2() called.")
    return a + b
if __name__=="__main__":
  a = example()
  a.myfunc()
  print(a.myfunc())
  print(a.myfunc2(1, 2))
  print(a.myfunc2(3, 4))

希望本文所述对大家的Python程序设计有所帮助。

Python 相关文章推荐
Python实现将DOC文档转换为PDF的方法
Jul 25 Python
python利用标准库如何获取本地IP示例详解
Nov 01 Python
DataFrame中去除指定列为空的行方法
Apr 08 Python
利用Python如何生成便签图片详解
Jul 09 Python
python字典值排序并取出前n个key值的方法
Oct 17 Python
在python中使用xlrd获取合并单元格的方法
Dec 26 Python
Python画图高斯分布的示例
Jul 10 Python
浅谈Python中函数的定义及其调用方法
Jul 19 Python
python3 实现爬取TOP500的音乐信息并存储到mongoDB数据库中
Aug 24 Python
python 实现快速生成连续、随机字母列表
Nov 28 Python
Python闭包及装饰器运行原理解析
Jun 17 Python
详解python定时简单爬取网页新闻存入数据库并发送邮件
Nov 27 Python
Python类属性与实例属性用法分析
May 09 #Python
python回调函数用法实例分析
May 09 #Python
python类和函数中使用静态变量的方法
May 09 #Python
Python实用日期时间处理方法汇总
May 09 #Python
python fabric使用笔记
May 09 #Python
Python字符串详细介绍
May 09 #Python
Python urllib、urllib2、httplib抓取网页代码实例
May 09 #Python
You might like
php设计模式 Composite (组合模式)
2011/06/26 PHP
解析php session_set_save_handler 函数的用法(mysql)
2013/06/29 PHP
PHP中几个可以提高运行效率的代码写法、技巧分享
2014/08/21 PHP
PHP面向对象之后期静态绑定功能介绍
2015/05/18 PHP
理解PHP中的Session及对Session有效期的控制
2016/01/08 PHP
Laravel多用户认证系统示例详解
2018/03/13 PHP
浅谈Laravel模板实体转义带来的坑
2019/10/22 PHP
用js判断浏览器是否是IE的比较好的办法
2007/05/08 Javascript
再论Javascript的类继承
2011/03/05 Javascript
Js为表单动态添加节点内容的方法
2015/02/10 Javascript
js实现缓冲运动效果的方法
2015/04/10 Javascript
javascript中Date format(js日期格式化)方法小结
2015/12/17 Javascript
Express与NodeJs创建服务器的两种方法
2017/02/06 NodeJs
html5+canvas实现支持触屏的签名插件教程
2017/05/08 Javascript
JavaScript对JSON数据进行排序和搜索
2017/07/24 Javascript
vue事件修饰符和按键修饰符用法总结
2017/07/25 Javascript
js 获取json数组里面数组的长度实例
2017/10/31 Javascript
JavaScript实现的滚动公告特效【基于jQuery】
2019/07/10 jQuery
Ant Design Vue 添加区分中英文的长度校验功能
2020/01/21 Javascript
[43:51]2014 DOTA2国际邀请赛中国区预选赛 Dream Times VS TongFu
2014/05/22 DOTA
python中遍历文件的3个方法
2014/09/02 Python
python实现基本进制转换的方法
2015/07/11 Python
Python多进程同步简单实现代码
2016/04/27 Python
Python 字典与字符串的互转实例
2017/01/13 Python
Python实现的排列组合计算操作示例
2017/10/13 Python
python如何实现反向迭代
2018/03/20 Python
Python实现检测文件MD5值的方法示例
2018/04/11 Python
一步步教你用python的scrapy编写一个爬虫
2019/04/17 Python
Python向excel中写入数据的方法
2019/05/05 Python
python根据字典的键来删除元素的方法
2020/08/16 Python
python自动从arxiv下载paper的示例代码
2020/12/05 Python
HTML5语音识别标签写法附图
2013/11/18 HTML / CSS
详解HTML5中CSS外观属性
2020/09/10 HTML / CSS
丹麦优惠购物网站:PLUSSHOP
2019/03/24 全球购物
DJI全球:DJI Global
2021/03/15 全球购物
大型活动策划方案
2014/01/12 职场文书