轻松理解 Python中的装饰器(decorator)

装饰器是Python中很重要的一个功能, 一句话总结装饰器就是: 将被装饰函数作为参数传入装饰函数中, 并实现装饰函数中的多余功能.

下面一一说明什么是装饰器:

def f1():
    print("Called f1")

print(f1)
<function f1 at 0x7fd2b87b8040>

我们定义了一个f1函数, 然后打印f1 显示的是这个函数的储存地址, 也就是说 function 在python 中是个 object, 可以作为参数传入 另一个function中.

def f2(f):
    f()


f2(f1)

output:
Called f1

我们定义如下函数:

def f1(func):
    def wrapper():
        print("Start")
        func()
        print("End")
        
    return wrapper

def f():
    print("Hello")

将f 作为参数传入f1中:

f1(f)

output:
<function __main__.f1.<locals>.wrapper()>

输入为 一个function. 因为f1返回的是 wrapper函数. 并没有调用wrapper函数. 下面调用wrapper函数:

f1(f)()

输出:
Start
Hello
End

也可以赋值给新的变量:

f = f1(f)
f()

输入:
Start
Hello
End

这就是装饰器了.  f为被装饰函数, 它被传入了装饰函数f1中, 并有了f1函数内部的功能. 用装饰器的写法就是:

@f1
def f():
    print("Hello")
    
f()

输出:
Start
Hello
End

但到这里 被装饰函数中没有参数, 如果传入参数 会产生error:

f("hi")

output:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [39], in <cell line: 1>()
----> 1 f("hi")

TypeError: wrapper() takes 0 positional arguments but 1 was given

如果想在被装饰函数中可传入参数的话, 可以如下这样修改装饰器:

def f1(func):
    def wrapper(*args, **kwargs):
        print("Start")
        func(*args, **kwargs)
        print("End")
        
    return wrapper

 让wrapper可以传入任何形式的参数

@f1
def f(a, b=9):
    print(a, b)
f(3)

输出:
Start
3 9
End

到这里 被装饰的函数都是print()的形式, 如果是return 的形式, 可以 在wrapper函数中加入return:

def f1(func):
    def wrapper(*args, **kwargs):
        print("Start")
        val = func(*args, **kwargs)
        print("End")
        return val 
    
    return wrapper

@f1 
def add(x, y):
    return x + y

print(add(4,5))

输入:
Start
End
9

总结, 建立一个装饰器, 给 被装饰函数 赋予可以输处 被装饰函数运行时间的功能:

import time 

def timer(func):
    def wrapper():
        before = time.time()
        func()
        print("Function took:", time.time() - before, "seconds")
        
    return wrapper 


@timer
def run():
    time.sleep(2)
    
run()


输出:
Function took: 2.005012035369873 seconds

猜你喜欢

转载自blog.csdn.net/bo17244504/article/details/125005690
今日推荐