九步学会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实现个性化词云的方法
Jun 16 Python
python处理数据,存进hive表的方法
Jul 04 Python
python 循环读取txt文档 并转换成csv的方法
Oct 26 Python
5分钟 Pipenv 上手指南
Dec 20 Python
Python3解释器知识点总结
Feb 19 Python
PyQt5 实现给窗口设置背景图片的方法
Jun 13 Python
python使用paramiko模块通过ssh2协议对交换机进行配置的方法
Jul 25 Python
PyCharm导入python项目并配置虚拟环境的教程详解
Oct 13 Python
Python super()方法原理详解
Mar 31 Python
pip install 使用国内镜像的方法示例
Apr 03 Python
jupyter notebook 重装教程
Apr 16 Python
pytest配置文件pytest.ini的详细使用
Apr 17 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分页函数
2006/10/09 PHP
php 过滤危险html代码
2009/06/29 PHP
PHP小程序自动提交到自助友情连接
2009/11/24 PHP
php中3种方法统计字符串中每种字符的个数并排序
2012/08/27 PHP
php 使用html5 XHR2实现上传文件与进度显示功能示例
2020/03/03 PHP
纯js实现div内图片自适应大小(已测试,兼容火狐)
2014/06/16 Javascript
javascript根据时间生成m位随机数最大13位
2014/10/30 Javascript
简单讲解AngularJS的Routing路由的定义与使用
2016/03/05 Javascript
javascript实现非常简单的小数取整功能示例
2017/06/13 Javascript
详解Node.js中的Async和Await函数
2018/02/22 Javascript
js技巧之十几行的代码实现vue.watch代码
2018/06/09 Javascript
ES6基础之展开语法(Spread syntax)
2019/02/21 Javascript
从0到1搭建Element的后台框架的方法步骤
2019/04/10 Javascript
如何正确理解vue中的key详解
2019/11/02 Javascript
antd vue table跨行合并单元格,并且自定义内容实例
2020/10/28 Javascript
Python使用xlrd模块操作Excel数据导入的方法
2015/05/26 Python
Python遍历目录并批量更换文件名和目录名的方法
2016/09/19 Python
python实现字符串连接的三种方法及其效率、适用场景详解
2017/01/13 Python
matplotlib绘制符合论文要求的图片实例(必看篇)
2017/06/02 Python
Python中fnmatch模块的使用详情
2018/11/30 Python
python 实现矩阵上下/左右翻转,转置的示例
2019/01/23 Python
python for 循环获取index索引的方法
2019/02/01 Python
Python爬虫爬取新闻资讯案例详解
2020/07/14 Python
Opencv python 图片生成视频的方法示例
2020/11/18 Python
CSS3五个技巧给你的网站带来出色的效果
2009/04/02 HTML / CSS
领先的荷兰线上超市:荷兰之家Holland at Home(支持中文)
2021/01/21 全球购物
Burt’s Bees英国官网:世界领先的天然个人护理品牌
2020/08/17 全球购物
敏捷开发的主要原则都有哪些
2015/04/26 面试题
自考生毕业自我鉴定
2013/10/10 职场文书
制药工程专业毕业生推荐信
2013/12/24 职场文书
优秀教师的感人事迹
2014/02/04 职场文书
政协调研汇报材料
2014/08/15 职场文书
合作协议书范本
2014/10/25 职场文书
css3带你实现3D转换效果
2022/02/24 HTML / CSS
Golang 链表的学习和使用
2022/04/19 Golang
win10如何快速切换窗口 win10切换窗口快捷键分享
2022/07/23 数码科技