九步学会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 相关文章推荐
Python3处理文件中每个词的方法
May 22 Python
详解详解Python中writelines()方法的使用
May 25 Python
Python socket网络编程TCP/IP服务器与客户端通信
Jan 05 Python
为什么选择python编程语言入门黑客攻防 给你几个理由!
Feb 02 Python
python 3.7.0 安装配置方法图文教程
Aug 27 Python
使用python对excle和json互相转换的示例
Oct 23 Python
Python内置random模块生成随机数的方法
May 31 Python
Python如何基于smtplib发不同格式的邮件
Dec 30 Python
Pytorch中实现只导入部分模型参数的方式
Jan 02 Python
Tensorflow实现在训练好的模型上进行测试
Jan 20 Python
Python如何读写CSV文件
Aug 13 Python
十个Python自动化常用操作,即拿即用
May 10 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 文章采集正则代码
2009/12/28 PHP
PHP获取当前日期所在星期(月份)的开始日期与结束日期(实现代码)
2013/06/18 PHP
php 一维数组的循环遍历实现代码
2017/04/10 PHP
详解将数据从Laravel传送到vue的四种方式
2019/10/16 PHP
window.parent调用父框架时 ie跟火狐不兼容问题
2009/07/30 Javascript
ASP中Sub和Function的区别说明
2020/08/30 Javascript
Jquery插件之打造自定义的select标签
2011/11/30 Javascript
Javascript 面向对象编程(coolshell)
2012/03/18 Javascript
Jquery实现搜索框提示功能示例代码
2013/08/13 Javascript
js动态切换图片的方法
2015/01/20 Javascript
Javascript中String的常用方法实例分析
2015/06/13 Javascript
jquery转盘抽奖功能实现
2015/11/13 Javascript
运用js教你轻松制作html音乐播放器
2020/04/17 Javascript
React 高阶组件入门介绍
2018/01/11 Javascript
微信小程序canvas绘制圆角base64图片的实现
2019/08/18 Javascript
npx create-react-app xxx创建项目报错的解决办法
2020/02/17 Javascript
JavaScript定时器使用方法详解
2020/03/26 Javascript
JavaScript 类的封装操作示例详解
2020/05/16 Javascript
python通过自定义isnumber函数判断字符串是否为数字的方法
2015/04/23 Python
python动态加载包的方法小结
2016/04/18 Python
Python绘制正余弦函数图像的方法
2018/08/28 Python
不知道这5种下划线的含义,你就不算真的会Python!
2018/10/09 Python
python实现栅栏加解密 支持密钥加密
2019/03/20 Python
Python数据结构与算法(几种排序)小结
2019/06/22 Python
Python利用Xpath选择器爬取京东网商品信息
2020/06/01 Python
Python 如何展开嵌套的序列
2020/08/01 Python
Python特殊属性property原理及使用方法解析
2020/10/09 Python
python 调用Google翻译接口的方法
2020/12/09 Python
校本教研工作制度
2014/01/22 职场文书
党员违纪检讨书
2014/02/18 职场文书
建材投资建议书
2014/05/16 职场文书
品质标语大全
2014/06/21 职场文书
社会发展项目建议书
2014/08/25 职场文书
刑事辩护授权委托书
2014/09/13 职场文书
警察群众路线对照检查材料思想汇报
2014/10/01 职场文书
演讲稿之我的初心我的成长
2019/08/12 职场文书