Python装饰器入门学习教程(九步学习)


Posted in Python onJanuary 28, 2016

装饰器(decorator)是一种高级Python语法。装饰器可以对一个函数、方法或者类进行加工。在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果。相对于其它方式,装饰器语法简单,代码可读性高。因此,装饰器在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中集合的内建函数和内建方法学习教程
Aug 19 Python
python3批量删除豆瓣分组下的好友的实现代码
Jun 07 Python
Python自动发邮件脚本
Mar 31 Python
python的paramiko模块实现远程控制和传输示例
Oct 13 Python
python输入错误密码用户锁定实现方法
Nov 27 Python
django自带的server 让外网主机访问方法
May 14 Python
django数据关系一对多、多对多模型、自关联的建立
Jul 24 Python
Matplotlib scatter绘制散点图的方法实现
Jan 02 Python
浅谈Python 参数与变量
Jun 20 Python
Python自动化之UnitTest框架实战记录
Sep 08 Python
使用豆瓣源来安装python中的第三方库方法
Jan 26 Python
使用Pytorch实现two-head(多输出)模型的操作
May 28 Python
基于Python如何使用AIML搭建聊天机器人
Jan 27 #Python
使用Python写个小监控
Jan 27 #Python
基于Python实现通过微信搜索功能查看谁把你删除了
Jan 27 #Python
Python图像灰度变换及图像数组操作
Jan 27 #Python
让python在hadoop上跑起来
Jan 27 #Python
CentOS安装pillow报错的解决方法
Jan 27 #Python
python实现文本去重且不打乱原本顺序
Jan 26 #Python
You might like
PHP 开发环境配置(Zend Studio)
2010/04/28 PHP
114啦源码(114la)不能生成地方房产和地方报刊问题4级页面0字节的解决方法
2012/01/12 PHP
php中serialize序列化与json性能测试的示例分析
2013/04/27 PHP
JS JavaScript获取Url参数,src属性参数
2021/03/09 Javascript
Google 静态地图API实现代码
2010/11/19 Javascript
jQuery插件-jRating评分插件源码分析及使用方法
2012/12/28 Javascript
JS定义回车事件(实现代码)
2013/07/08 Javascript
js 3秒后跳转页面的实现代码
2014/03/10 Javascript
jQuery实现table隔行换色和鼠标经过变色的两种方法
2014/06/15 Javascript
基于jQuery实现复选框是否选中进行答题提示
2015/12/10 Javascript
jQuery实现简单的DIV拖动效果
2016/02/19 Javascript
Angular外部使用js调用Angular控制器中的函数方法或变量用法示例
2016/08/05 Javascript
JS实现图片上传预览功能
2016/11/21 Javascript
Bootstrap基本组件学习笔记之缩略图(13)
2016/12/08 Javascript
js+html制作简单日历的方法
2017/06/27 Javascript
关于webpack代码拆分的解析
2017/07/20 Javascript
js实现rem自动匹配计算font-size的示例
2017/11/18 Javascript
详解react-router 4.0 下服务器如何配合BrowserRouter
2017/12/29 Javascript
Angular 如何使用第三方库的方法
2018/04/18 Javascript
通过实例解析json与jsonp原理及使用方法
2020/09/27 Javascript
flask中使用SQLAlchemy进行辅助开发的代码
2013/02/10 Python
python 文件查找及内容匹配方法
2018/10/25 Python
使用Django2快速开发Web项目的详细步骤
2019/01/06 Python
使用python批量修改文件名的方法(视频合并时)
2020/03/24 Python
django 做 migrate 时 表已存在的处理方法
2019/08/31 Python
Python函数的定义方式与函数参数问题实例分析
2019/12/26 Python
Python datetime 格式化 明天,昨天实例
2020/03/02 Python
python Canny边缘检测算法的实现
2020/04/24 Python
如何利用python生成MD5并去重
2020/12/07 Python
美国设计师精美珠宝购物网:Netaya
2016/08/28 全球购物
新西兰第一的行李箱网站:luggage.co.nz
2019/07/22 全球购物
泰海淘:泰国king Power王权免税集团旗下跨境海淘综合型电商
2020/07/26 全球购物
校园报刊亭的创业计划书
2014/01/02 职场文书
网络书店创业计划书
2014/02/07 职场文书
2015圣诞节贺卡寄语
2015/03/24 职场文书
全民创业工作总结
2015/08/13 职场文书