九步学会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打开网页和暂停实例
Sep 30 Python
numpy中以文本的方式存储以及读取数据方法
Jun 04 Python
python实现点对点聊天程序
Jul 28 Python
Python中的支持向量机SVM的使用(附实例代码)
Jun 26 Python
python利用wx实现界面按钮和按钮监听和字体改变的方法
Jul 17 Python
Python Pillow.Image 图像保存和参数选择方式
Jan 09 Python
使用Pycharm(Python工具)新建项目及创建Python文件的教程
Apr 26 Python
简单了解Python变量作用域正确使用方法
Jun 12 Python
Python实现Keras搭建神经网络训练分类模型教程
Jun 12 Python
Keras模型转成tensorflow的.pb操作
Jul 06 Python
Python读写压缩文件的方法
Jul 30 Python
Python爬虫UA伪装爬取的实例讲解
Feb 19 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+FLASH实现上传文件进度条相关文件 下载
2007/07/21 PHP
PHP 出现乱码和Sessions验证问题的解决方法!
2008/12/06 PHP
php实现无限级分类实现代码(递归方法)
2011/01/01 PHP
PHP 动态生成静态HTML页面示例代码
2014/01/15 PHP
PHP中的表达式简述
2016/05/29 PHP
thinkphp jquery实现图片上传和预览效果
2020/07/22 PHP
PHP-FPM和Nginx的通信机制详解
2019/02/01 PHP
Laravel核心解读之异常处理的实践过程
2019/02/24 PHP
jQuery与ExtJS之选择实例分析
2010/08/19 Javascript
在Ubuntu上安装最新版本的Node.js
2014/07/14 Javascript
如何用js 实现依赖注入的思想,后端框架思想搬到前端来
2015/08/03 Javascript
jquery实现滑屏大图定时收缩为小banner图片的广告代码
2015/09/02 Javascript
AngularJS的ng Http Request与response格式转换方法
2016/11/07 Javascript
关于jQuery中fade(),show()起始位置的一点小发现
2017/04/25 jQuery
vue.js 获取select中的value实例
2018/03/01 Javascript
详解基于vue-cli3快速发布一个fullpage组件
2019/03/08 Javascript
JavaScript惰性载入函数实例分析
2019/03/27 Javascript
深入浅析vue-cli@3.0 使用及配置说明
2019/05/08 Javascript
微信小程序录音实现功能并上传(使用node解析接收)
2020/02/26 Javascript
JS实现拖动模糊框特效
2020/08/25 Javascript
Python实现基本数据结构中队列的操作方法示例
2017/12/04 Python
Python中xml和dict格式转换的示例代码
2019/11/07 Python
Python实现猜年龄游戏代码实例
2020/03/25 Python
HTML5实现移动端弹幕动画效果
2019/08/01 HTML / CSS
越南电子产品购物网站:FPT Shop
2017/12/02 全球购物
荷兰电脑专场:Paradigit
2018/05/05 全球购物
总经理职责
2013/12/22 职场文书
中文教师求职信
2014/02/22 职场文书
国际经济贸易专业自荐信
2014/06/13 职场文书
授权收款委托书
2014/09/23 职场文书
银行授权委托书样本
2014/10/13 职场文书
道歉短信大全
2015/05/12 职场文书
入学证明
2015/06/23 职场文书
六一文艺汇演主持词
2015/06/30 职场文书
html5调用摄像头截图功能
2022/01/18 Javascript
利用Redis实现点赞功能的示例代码
2022/06/28 Redis