九步学会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回调函数的使用方法
Jan 23 Python
Python实现PS图像调整之对比度调整功能示例
Jan 26 Python
Python实现时钟显示效果思路详解
Apr 11 Python
Python脚本完成post接口测试的实例
Dec 17 Python
浅谈python 读excel数值为浮点型的问题
Dec 25 Python
详解django中url路由配置及渲染方式
Feb 25 Python
详解如何管理多个Python版本和虚拟环境
May 10 Python
Pycharm保存不能自动同步到远程服务器的解决方法
Jun 27 Python
python+selenium 鼠标事件操作方法
Aug 24 Python
python数据库开发之MongoDB安装及Python3操作MongoDB数据库详细方法与实例
Mar 18 Python
基于python实现ROC曲线绘制广场解析
Jun 28 Python
利用Python实现最小二乘法与梯度下降算法
Feb 21 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桌面中心(四) 数据显示
2007/03/11 PHP
php字符串截取中文截取2,单字节截取模式
2007/12/10 PHP
PHPMailer邮件发送的实现代码
2013/05/04 PHP
WordPress开发中自定义菜单的相关PHP函数使用简介
2016/01/05 PHP
PHP使用Redis替代文件存储Session的方法
2017/02/15 PHP
Laravel框架分页实现方法分析
2018/06/12 PHP
js内存泄露的几种情况详细探讨
2013/05/31 Javascript
jQuery 计算iframe 窗口大小的方法
2014/05/13 Javascript
JS判断客服QQ号在线还是离线状态的方法
2015/01/13 Javascript
jQuery检测鼠标左键和右键点击的方法
2015/03/17 Javascript
jQuery实现仿Alipay支付宝首页全屏焦点图切换特效
2015/05/04 Javascript
XML文件转化成NSData对象的方法
2015/08/12 Javascript
Bootstrap基本样式学习笔记之标签(5)
2016/12/07 Javascript
BootStrapValidator校验方式
2016/12/19 Javascript
微信小程序 弹窗自定义实例代码
2017/03/08 Javascript
layui分页效果实现代码
2017/05/19 Javascript
ES6的异步终极解决方案分享
2019/07/11 Javascript
[06:24]DOTA2亚洲邀请赛小组赛第三日 TOP10精彩集锦
2015/02/01 DOTA
[46:57]EG vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
ssh批量登录并执行命令的python实现代码
2012/05/25 Python
Python列表append和+的区别浅析
2015/02/02 Python
简单的编程0基础下Python入门指引
2015/04/01 Python
Python的Bottle框架中获取制定cookie的教程
2015/04/24 Python
Python在for循环中更改list值的方法【推荐】
2018/08/17 Python
python实现复制文件到指定目录
2019/10/16 Python
使用IDLE的Python shell窗口实例详解
2019/11/19 Python
Pytorch训练过程出现nan的解决方式
2020/01/02 Python
Python如何实现小程序 无限求和平均
2020/02/18 Python
澳大利亚珍珠首饰购物网站:Vayo Pearls
2019/03/11 全球购物
英国在线玫瑰专家:InterRose
2019/12/01 全球购物
人力资源部门的主要职能
2014/02/22 职场文书
和解协议书
2014/04/16 职场文书
党代会心得体会
2014/09/04 职场文书
2015年街道除四害工作总结
2015/05/15 职场文书
实习单位鉴定意见
2015/06/04 职场文书
CSS 左边固定宽右边自适应的6种方法
2022/05/15 HTML / CSS