九步学会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的自动化部署模块Fabric的安装及使用指南
Jan 19 Python
浅谈python对象数据的读写权限
Sep 12 Python
Python实现拷贝多个文件到同一目录的方法
Sep 19 Python
Python实现七彩蟒蛇绘制实例代码
Jan 16 Python
Python中存取文件的4种不同操作
Jul 02 Python
python 实现A*算法的示例代码
Aug 13 Python
Python 实现数据结构中的的栈队列
May 16 Python
对Django中static(静态)文件详解以及{% static %}标签的使用方法
Jul 28 Python
python tqdm 实现滚动条不上下滚动代码(保持一行内滚动)
Feb 19 Python
python对execl 处理操作代码
Jun 22 Python
python自动化之如何利用allure生成测试报告
May 02 Python
Python使用pandas导入csv文件内容的示例代码
Dec 24 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/11/25 PHP
IIS php环境配置PHP5 MySQL5 ZendOptimizer phpmyadmin安装与配置
2008/11/18 PHP
php中判断字符串是否全是中文或含有中文的实现代码
2011/09/16 PHP
PHP判断远程url是否有效的几种方法小结
2011/10/08 PHP
百度地图API应用之获取用户的具体位置
2014/06/10 PHP
PHP 记录访客的浏览信息方法
2018/01/29 PHP
javascript对数组的常用操作代码 数组方法总汇
2011/01/27 Javascript
jqgrid 简单学习笔记
2011/05/03 Javascript
JQuery学习笔录 简单的JQuery
2012/04/09 Javascript
jQuery中iframe的操作(点击按钮新增窗口)
2016/04/20 Javascript
浅谈ajax请求不同页面的微信JSSDK问题
2018/02/26 Javascript
Vue使用json-server进行后端数据模拟功能
2018/04/17 Javascript
详解webpack 最简打包结果分析
2019/02/20 Javascript
vue选项卡切换登录方式小案例
2019/09/27 Javascript
ES6中let、const的区别及变量的解构赋值操作方法实例分析
2019/10/15 Javascript
一篇文章带你浅入webpack的DLL优化打包
2020/02/20 Javascript
解决vue安装less报错Failed to compile with 1 errors的问题
2020/10/22 Javascript
paramiko模块安装和使用(远程登录服务器)
2014/01/27 Python
python文件和目录操作方法大全(含实例)
2014/03/12 Python
python多线程操作实例
2014/11/21 Python
Python中最大递归深度值的探讨
2019/03/05 Python
python实现微信防撤回神器
2019/04/29 Python
python+selenium实现自动化百度搜索关键词
2019/06/03 Python
Python实现的对一个数进行因式分解操作示例
2019/06/27 Python
Python模块zipfile原理及使用方法详解
2020/08/04 Python
深入解析HTML5中的Blob对象的使用
2015/09/08 HTML / CSS
交通法规咨询中心工作职责
2013/11/27 职场文书
大学生素质拓展活动方案
2014/02/11 职场文书
产假请假条
2014/04/10 职场文书
小学生综合素质评语
2014/04/23 职场文书
求职信范文大全
2014/05/26 职场文书
个人工作总结范文2014
2014/11/07 职场文书
晚会开场白和结束语
2015/05/29 职场文书
三国演义读书笔记
2015/06/25 职场文书
Dashboard管理Kubernetes集群与API访问配置
2022/04/01 Servers
实现GO语言对数组切片去重
2022/04/20 Golang