一文了解python装饰器

1. 闭包函数

要想了解装饰器,首先要了解一个概念,闭包。

我们先来看看闭包函数。我们知道python是一种面向对象的编程语言,也就是说python中一切皆对象,所以我们在函数中定义函数是合法的行为,我们管这种函数叫内嵌函数。这种函数只可以在外部函数的作用域内被正常调用

def outer(x):
    print(f'x = {x}') # x = 6
    def inner(y):
        print(f'y = {y}') # y = 5
        print(f'x + y = {x+y}') # x + y = 11
        return x + y
    return inner

outer(6)(5)

2. python装饰器

好了,我们现在对闭包有一定的了解了,下面再来看看装饰器。python装饰器本质上就是一个函数,它可以让其他函数在 不需要做任何代码变动的前提下增加额外的功能 ,装饰器的返回值也是一个 函数对象(函数的指针)在这里插入代码片

2.1 函数装饰器

(1)函数的函数装饰器

下列功能为测试func函数的耗时程序,其中func可以为任意传入函数。为了测试hello函数的耗时,有两种做法,一种是将hello传入decorator函数中,另一种是将hello添加装饰器

  • 普通函数调用实现
import time

def decorator(func):
    print("1. start decorator!")
    def wrapper(*args, **kwargs):
        print("4. wrapper")
        print(f"func name is :  {func.__name__}") # 输出传入的func名字
        start_time = time.time() #秒
        func()
        end_time = time.time()
        print("7. time: ",end_time - start_time) # 测试耗时

    print("2. end decorator!")
    return wrapper

def hello():
    print("5. hello")
    time.sleep(1.3)
    print("6. world")

if __name__ == '__main__':
    print('*******开始main*********')
    f = decorator(hello)
    print("3. start wrapper!")
    f()# 执行闭包函数,也就是wrapper

输出:

*******开始main*********
1. start decorator!
2. end decorator!
3. start wrapper!
4. wrapper
func name is :  hello
5. hello
6. world
7. time:  1.301443338394165
  • 装饰器实现

装饰器的实现方式,并不会对源程序做任何改变,如下所示。

import time

def decorator(func):
    print("1. start decorator!")
    def wrapper(*args, **kwargs):
        print("4. wrapper")
        print(f"func name is :  {func.__name__}") # 输出传入的func名字
        start_time = time.time() #秒
        func()
        end_time = time.time()
        print("7. time: ",end_time - start_time) # 测试耗时

    print("2. end decorator!")
    return wrapper

@decorator
def hello():
    print("5. hello")
    time.sleep(1.3)
    print("6. world")

if __name__ == '__main__':
    print('*******开始main*********')
    hello()

输出:

1. start decorator!
2. end decorator!
*******开始main*********
4. wrapper
func name is :  hello
5. hello
6. world
7. time:  1.3001999855041504

(2)类方法的函数装饰器

对于类方法来说,都会有一个默认的参数self,它实际表示的是类的一个实例,所以在装饰器的内部函数wrapper也要传入一个参数 - me_instance就表示将类的实例p1传给wrapper,其他的用法都和函数装饰器相同。

import time

def decorator(func):
    def wrapper(me_instance):
        start_time = time.time()
        func(me_instance)
        end_time = time.time()
        print(end_time - start_time)
    return wrapper

class Method(object):

    @decorator
    def func(self):
        time.sleep(0.8)

p1 = Method()
p1.func() # 函数调用

2.2 类装饰器

class Decorator(object):
    def __init__(self, f):
        self.f = f
    def __call__(self):
        print("decorator start")
        self.f()
        print("decorator end")

@Decorator
def func():
    print("func")

f = func
print("start call!")
f()

输出:

start call!
decorator start
func
decorator end

参考:https://www.cnblogs.com/lianyingteng/p/7743876.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

非晚非晚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值