装饰器1-工作原理

装饰器工作原理

先用一个例子体会一下

def funA(fn):       # 装饰器函数
    print("--1--")
    fn()
    print("--2--")
    print("******")
    return "--3--"

def funB():
    print("--funB--")

funB = funA(funB)                ###
print(funB)

使用装饰器之后,代码就可以变成这样

def funA(fn):       # 装饰器函数
    print("--1--")
    fn()
    print("--2--")
    print("******")
    return "--3--"

@funA                      
## 等价于 funB = funA(funB)
def funB():
    print("--funB--")

print(funB)

输出结果如下

--1--
--funB--
--2--
******
--3--
装饰器完成了以下功能:
  • 将funB作为参数传给funA()函数
  • 将funA函数执行完的返回值return反馈给funB
总结:

所谓函数装饰器,就是通过装饰器函数,在不修改原函数的前提下,来对函数的功能进行合理的扩充。

修饰的函数不再是原来的函数,而是被替换成一个新的东西(取决于装饰器的返回值),即如果装饰器函数的返回值为普通变量,那么被修饰的函数名就变成了变量名;同样,如果装饰器返回的是一个函数的名称,怎么被修饰的函数名依然表示一个函数。

函数名字和注释文档

def a_new_decorator(a_func):
    def wrapTheFunction():
        print("before executing a_func()")
        a_func()
        print("after executing a_func()")
        print("************")
    return wrapTheFunction
 
@a_new_decorator
# a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
def a_function_requiring_decoration():
    print("I am the function")

a_function_requiring_decoration()

print(a_new_decorator.__name__)         # a_new_decorator
print(a_function_requiring_decoration.__name__)     # wrapTheFunction

a_function_requiring_decoration重写了
python提供一个简单函数functools.wraps修改

from functools import wraps

def a_new_decorator(a_func):
    @wraps(a_func)
    def wrapTheFunction():
        print("before executing a_func()")
        a_func()
        print("after executing a_func()")
    return wrapTheFunction

@a_new_decorator
def a_function_requiring_decoration():
    print("I am the function")

print(a_function_requiring_decoration.__name__)     # a_function_requiring_decoration
注意

@wraps接受一个函数进行装饰,并加入了复制函数名称、注释文档、参数列表等功能。可以让我们在装饰器里面访问在装饰之前的函数的属性。

带有多个参数
from functools import wraps

def decorator_name(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if not can_run:                 # False
            return "Function will not run"
        return f(*args, **kwargs)       # True
    return decorated
 
@decorator_name
def func():
    return("Function is running")
 
can_run = True
print(func())
# Output: Function is running
can_run = False
print(func())
# Output: Function will not run

日志中常用到装饰器

from functools import wraps
 
def logit(func):
    @wraps(func)
    def with_logging(*args, **kwargs):
        print(func.__name__ + " was called")
        return func(*args, **kwargs)
    return with_logging
 
@logit
def addition_func(x):
   """Do some math."""
   return x + x
 
result = addition_func(4)
# Output: addition_func was called
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。