Python装饰器学习笔记
2015-05-31 00:00
691 查看
摘要: 简单的python装饰器介绍
之前在看<<Python核心编程>>时遇到decorator时看得云里雾里,然后也没去多管,想到等以后遇到这个问题 时再去解决。今天在看Django代码时看到login_required等装饰器时又遇到这个东西了,于是在网上找了一些文档重新学了一下,在此做一个 总结。
1. 装饰器含义
装 饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器, 我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
2. 装饰器语法
(1)无参数装饰器
def deco(func):
print("deco")
return func
@deco
def foo():
print("foo")
foo()
第一个函数deco是装饰函数,它的参数就是被装饰的函数对象。我们可以在deco函数内对传入的函数对象做一番“装饰”,然后返回这个对象(记住一定要返回 ,不然外面调用foo的地方将会无函数可用。实际上此时foo=deco(foo)
(2)有参数装饰器
被装饰函数无参数
def deco(argv):
def decorator(func):
print("decorator")
return func
print("deco")
print(argv)
return decorator
@deco ("123")
def foo():
print("foo")
foo()
第一个函数deco是装饰函数,它的参数是用来“加强装饰”的。由于此函数并非被装饰的函数对象,所以在内部必须至少创建一个接受被装饰函数的函数,然后返回这个对象。实际上此时foo = deco(argv)(foo)
被装饰函数也有参数
from functools import wraps
def deco(argv):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("wrapper")
return func(*args, **kwargs)
print("decorator")
return wrapper
print("deco")
print(argv)
return decorator
@deco ("123")
def foo(data):
"this is foo"
print("foo")
print(data)
foo("afdasdf")
print(foo.__name__, foo.__doc__)
在decorator函数内部还需要定义一个函数来接受被装饰函数的参数。此时foo = deco(argv)(foo)(data)
首 先注意第5行,如果注释这一行,foo.__name__将是'wrapper',使用这个装饰器后装饰之后的foo.__name__将还是原来的 foo,wraps装饰器是将func的常用属性赋给了wrapper函数。另外相信你也注意到了,这个装饰器竟然带有一个参数。实际上,他还有另外两个 可选的参数,assigned中的属性名将使用赋值的方式替换,而updated中的属性名将使用update的方式合并,你可以通过查看 functools的源代码获得它们的默认值。对于这个装饰器,相当于wrapper = functools.wraps(func)(wrapper)
(3)多装饰器组合使用
def deco1(func):
print("deco1")
return func
def deco2(func):
print("deco2")
return func
@deco2
@deco1
def foo():
print("foo")
foo()
注意多个装饰器的执行顺序,应该是先执行下面的,然后是上面的。这里应先执行deco1,然后是deco2。
(4)例子
def makebold(func):
def wrapped():
return "<b>" + func() + "</b>"
return wrapped
def makeitalic(func):
def wrapped():
return "<i>" + func() + "</i>"
return wrapped
@makebold
@makeitalic
def say():
return "Hello"
print(say())
#output
'''''
<b><i>Hello</i></b>
'''
3. 体会
当多个函数有重复代码时可以将此部分代码单独拿出来整理成一个装饰器,然后对每个函数调用该装饰器,这样可以实现代码的复用,而且可以让原来的函数更轻便。
还有就是当我们需要为多个已经写好的函数添加一个共同功能,比如检查参数的合法性。我们就可以单独写一个检查合法性的装饰器,然后在每个需要检查参数合法性的函数出调用即可,而不用去每个函数内部修改。
之前在看<<Python核心编程>>时遇到decorator时看得云里雾里,然后也没去多管,想到等以后遇到这个问题 时再去解决。今天在看Django代码时看到login_required等装饰器时又遇到这个东西了,于是在网上找了一些文档重新学了一下,在此做一个 总结。
1. 装饰器含义
装 饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器, 我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
2. 装饰器语法
(1)无参数装饰器
def deco(func):
print("deco")
return func
@deco
def foo():
print("foo")
foo()
第一个函数deco是装饰函数,它的参数就是被装饰的函数对象。我们可以在deco函数内对传入的函数对象做一番“装饰”,然后返回这个对象(记住一定要返回 ,不然外面调用foo的地方将会无函数可用。实际上此时foo=deco(foo)
(2)有参数装饰器
被装饰函数无参数
def deco(argv):
def decorator(func):
print("decorator")
return func
print("deco")
print(argv)
return decorator
@deco ("123")
def foo():
print("foo")
foo()
第一个函数deco是装饰函数,它的参数是用来“加强装饰”的。由于此函数并非被装饰的函数对象,所以在内部必须至少创建一个接受被装饰函数的函数,然后返回这个对象。实际上此时foo = deco(argv)(foo)
被装饰函数也有参数
from functools import wraps
def deco(argv):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("wrapper")
return func(*args, **kwargs)
print("decorator")
return wrapper
print("deco")
print(argv)
return decorator
@deco ("123")
def foo(data):
"this is foo"
print("foo")
print(data)
foo("afdasdf")
print(foo.__name__, foo.__doc__)
在decorator函数内部还需要定义一个函数来接受被装饰函数的参数。此时foo = deco(argv)(foo)(data)
首 先注意第5行,如果注释这一行,foo.__name__将是'wrapper',使用这个装饰器后装饰之后的foo.__name__将还是原来的 foo,wraps装饰器是将func的常用属性赋给了wrapper函数。另外相信你也注意到了,这个装饰器竟然带有一个参数。实际上,他还有另外两个 可选的参数,assigned中的属性名将使用赋值的方式替换,而updated中的属性名将使用update的方式合并,你可以通过查看 functools的源代码获得它们的默认值。对于这个装饰器,相当于wrapper = functools.wraps(func)(wrapper)
(3)多装饰器组合使用
def deco1(func):
print("deco1")
return func
def deco2(func):
print("deco2")
return func
@deco2
@deco1
def foo():
print("foo")
foo()
注意多个装饰器的执行顺序,应该是先执行下面的,然后是上面的。这里应先执行deco1,然后是deco2。
(4)例子
def makebold(func):
def wrapped():
return "<b>" + func() + "</b>"
return wrapped
def makeitalic(func):
def wrapped():
return "<i>" + func() + "</i>"
return wrapped
@makebold
@makeitalic
def say():
return "Hello"
print(say())
#output
'''''
<b><i>Hello</i></b>
'''
3. 体会
当多个函数有重复代码时可以将此部分代码单独拿出来整理成一个装饰器,然后对每个函数调用该装饰器,这样可以实现代码的复用,而且可以让原来的函数更轻便。
还有就是当我们需要为多个已经写好的函数添加一个共同功能,比如检查参数的合法性。我们就可以单独写一个检查合法性的装饰器,然后在每个需要检查参数合法性的函数出调用即可,而不用去每个函数内部修改。
相关文章推荐
- Python动态类型的学习---引用的理解
- Python3写爬虫(四)多线程实现数据爬取
- 垃圾邮件过滤器 python简单实现
- 下载并遍历 names.txt 文件,输出长度最长的回文人名。
- install and upgrade scrapy
- Scrapy的架构介绍
- Centos6 编译安装Python
- 使用Python生成Excel格式的图片
- 让Python文件也可以当bat文件运行
- [Python]推算数独
- Python中zip()函数用法举例
- Python中map()函数浅析
- Python在CAM软件Genesis2000中的应用
- 使用Shiboken为C++和Qt库创建Python绑定
- FREEBASIC 编译可被python调用的dll函数示例
- Python 七步捉虫法
- Python实现的基于ADB的Android远程工具