九步学会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多线程编程(三):threading.Thread类的重要函数和方法
Apr 05 Python
Python自动化开发学习之三级菜单制作
Jul 14 Python
python 接口_从协议到抽象基类详解
Aug 24 Python
Python基于time模块求程序运行时间的方法
Sep 18 Python
python读取和保存图片5种方法对比
Sep 12 Python
Python global全局变量函数详解
Sep 18 Python
python  文件的基本操作 菜中菜功能的实例代码
Jul 17 Python
pytorch三层全连接层实现手写字母识别方式
Jan 14 Python
Python Numpy 控制台完全输出ndarray的实现
Feb 19 Python
python实现定时发送邮件到指定邮箱
Dec 23 Python
Python利用socket模块开发简单的端口扫描工具的实现
Jan 27 Python
Pytorch如何切换 cpu和gpu的使用详解
Mar 01 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
thinkPHP的表达式查询用法详解
2016/09/14 PHP
利用PHP抓取百度阅读的方法示例
2016/12/18 PHP
PHP判断是手机端还是PC端 PHP判断是否是微信浏览器
2017/03/15 PHP
php从数据库中获取数据用ajax传送到前台的方法
2018/08/20 PHP
Locate a File Using a File Open Dialog Box
2007/06/18 Javascript
jquery ajax return没有返回值的解决方法
2011/10/20 Javascript
基于jQuery的获取标签名的代码
2012/07/16 Javascript
jQuery在ul中显示某个li索引号的方法
2015/03/17 Javascript
jQuery检测滚动条是否到达底部
2015/12/15 Javascript
JQuery.validate在ie8下不支持的快速解决方法
2016/05/18 Javascript
提高JavaScript执行效率的23个实用技巧
2017/03/01 Javascript
vue学习笔记之v-if和v-show的区别
2017/09/20 Javascript
bootstrap模态框嵌套、tabindex属性、去除阴影的示例代码
2017/10/17 Javascript
Angular 4中如何显示内容的CSS样式示例代码
2017/11/06 Javascript
webpack4.0 入门实践教程
2018/10/08 Javascript
使用jquery-easyui的布局layout写后台管理页面的代码详解
2019/06/19 jQuery
js实现淘宝浏览商品放大镜功能
2020/10/28 Javascript
Python中的对象,方法,类,实例,函数用法分析
2015/01/15 Python
python中文乱码不着急,先看懂字节和字符
2017/12/20 Python
在dataframe两列日期相减并且得到具体的月数实例
2018/07/03 Python
解决python 无法加载downsample模型的问题
2018/10/25 Python
Python3 利用requests 库进行post携带账号密码请求数据的方法
2018/10/26 Python
详解Python中字符串前“b”,“r”,“u”,“f”的作用
2019/12/18 Python
Tensorflow限制CPU个数实例
2020/02/06 Python
Python爬取你好李焕英豆瓣短评生成词云的示例代码
2021/02/24 Python
CSS3媒体查询(Media Queries)介绍
2013/09/12 HTML / CSS
美体小铺英国官网:The Body Shop英国
2017/01/24 全球购物
介绍一下linux的文件权限
2012/02/15 面试题
出口公司经理求职简历中的自我评价
2013/10/13 职场文书
小学生红领巾广播稿
2014/01/21 职场文书
《找不到快乐的波斯猫》教学反思
2014/02/24 职场文书
公务员保密承诺书
2014/03/27 职场文书
退税申请报告怎么写
2015/05/18 职场文书
幼儿园教师读书笔记
2015/06/29 职场文书
Redis过期数据是否会被立马删除
2022/07/23 Redis