装饰器 decorator 2018 / 8 / 11
==================================================================
1.1.定义:
# 在代码运行期间动态增加功能的方式,称之为装饰器Decorator
# decorator是一个返回函数的高阶函数;函数赋值给变量,通过变量调用该函数。
==================================================================
1.2.例
# 实例1:定义decorator无参数:
import functools
def log(func):
print('装饰器开始...')
@functools.wraps(func)
def inner(*args, **kwargs):
print('ready call add...')
return func(*args, **kwargs) # 无返回值可省略return
return inner
@log # 相当于add=log(add)
def add(a, b):
print('runing add...' )
return a + b
#调用
print('a+b= %s' % add(2, 4))
#装饰器开始...
#ready call add...
#runing add...
#a+b= 6
# 实例2:装饰器输入参数
import functools
def log(name='Tom'):
print('装饰器开始...')
def inner_log(func):
print('inner_log start...')
def inner(*args, **kwargs):
inner.__name__ = func.__name__
print('%s ready call %s...' % (name,inner.__name__))
return func(*args, **kwargs)
return inner
return inner_log
@log('John') # add = log('John')(add)
def add(a, b):
print('runing add...')
return a + b
#调用:
print('a+b= %s' % add(2, 4))
# 装饰器开始...
# inner_log start...
# John ready call add...
# runing add...
# a+b= 6
# 实例3:协程
def coroutine(func):
def start(*args, **kwargs):
g = func(*args, **kwargs)
next(g)
return g
return start
@coroutine
def receiver():
print('ready to receive')
while True:
n = (yield)
print('got %s' % n)
#调用:
r = receiver()
r.send('hello world')
#ready to receive
# got hello world
===================================================================
2.类装饰器
#装饰器函数是一个接口约束,必须接受callable对象作为参数,返回callable对象。
#callable对象是函数,对象重写call方法
#实例1:无参数类装饰器
class log (object):
def __init__(self, func):
print('func name = %s ' % func.__name__)
self.__func = func
def __call__(self, *args, **kwargs):
print('装饰器开始...')
return self.__func(*args, **kwargs)
@log
def add(x, y):
print('runing add...' )
return x + y
#调用:
print('add()=', add(2, 4))
#func name = add
#装饰器开始...
#runing add...
#add()= 6
#实例2:带参数类装饰器
class log(object):
def __init__(self, level='INFO'):
self.level = level
def __call__(self, func): # 接受函数
def wrapper(*args, **kwargs):
print("装饰器{}开始...[ enter function {}()]".format(
self.level,func.__name__))
func(*args, **kwargs)
return wrapper # 返回函数
@log('INFO')
def add(x,y):
print("runing add...[z={}]".format(x+y))
#调用:
add(2,3)
# 装饰器INFO开始...[ enter function add()]
# runing add...[z=5]
=================================================================
3.两个装饰器执行流程
def log1(func):
print('----a----')
def inner(*args, **kwargs):
print('----1----')
return ('log1=%s' % func(*args, **kwargs))
return inner
def log2(func):
print('----b----')
def inner(*args, **kwargs):
print('----2----')
return ('log2=%s' % func(*args, **kwargs))
return inner
@log1
@log2
def add(x, y):
print('----3----')
return x + y
#调用:
ret = add(2, 4)
print(ret)
##输出结果:
#----b----
#----a----
#----1----
#----2----
#----3----
#log1=log2=6
#
"""
说明:
1)先用第二个装饰器(log2)进行装饰再用第一个装饰器(log1)进行装饰
调用过程中,先执行第一个装饰器(log1),接着再执行第二个装饰器(log2)。
2)装饰时机
在执行到 @ log1时,需要对下面的函数进行装饰,此时解释器继续往下走,
发现并不是一个函数名,而又是一个装饰器,这时@log1装饰器暂停执行 ,
执行接下来装饰器 @ log2,接着把add函数名传入装饰器函数从而打印’b’
在log2装饰完后此时add指向log2的inner函数地址,这时返回来执行 @ log1
接着把新add传入log1装饰器函数中,因此打印了’a’。
调用add函数的时候,根据上述分析,此时add指向log1.inner函数,因此会
先打印‘1‘,接下来,在调用func()的时候,其实是调用的log2.inner()函数,
所以打印‘2‘,在log2.inner中,调用的func其实才是我们最原声的add函数,
所以打印原add函数中的‘3‘,所以在一层层调完之后,打印的结果为
log1 = log2 = 6
"""
=================================================================
4.other
4.1.装饰器函数—传递文档说明
def wrap(func):
def call(*args,**kwargs):
return func(*args,**kwargs)
call.__doc__=func.__doc__
call.__name__=func.__name__
return call
=================================================================
4.2. from functools import wraps
#模块@wraps(func)装饰器可以将属性从func传递给要定义的包装器函数
def wrap(func):
@wraps(func)
def call(*args,**kwargs):
return func(*args,**kwargs)
return call
@wrap
def factorial(n):
"""tcy define function used wraps."""
# 调用:
help(factorial)
# 结果:
# Help on function factorial in module __main__:
# factorial(n)
# tcy define function used wraps.
================================================================
4.3.#函数属性
def wrap(func):
def call(*args,**kwargs):
return func(*args,**kwargs)
call.__doc__=func.__doc__
call.__name__=func.__name__
call.__dict__.update(func.__dict__)
return call
@wrap
def foo():
'foo function define'
pass
#调用:
foo.secure=1
foo.private=1
help(foo)
print(foo.__dict__)
# 结果
'''''''''
Help on function foo in module __main__:
foo(*args, **kwargs)
foo function define
{'secure': 1, 'private': 1}
'''
=================================================================
python 学习汇总23:装饰器 decorator( tcy)
猜你喜欢
转载自blog.csdn.net/tcy23456/article/details/84072149
今日推荐
周排行