python进阶二:函数装饰器、类装饰器、如何保证原函数的元信息、装饰器嵌套、装饰器应用场景

本文深入探讨Python装饰器,包括简单装饰器、带参数的装饰器、带有自定义参数的装饰器、如何保留原函数元信息、类装饰器的使用以及装饰器的嵌套。同时,阐述了装饰器在身份认证、日志记录、缓存和输入合法性检查等场景中的实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

装饰器

一、简单装饰器

def my_decorator(func):
    def wrapper():
        print('wrapper of decorator!')
        func()
    return wrapper

def greet():
    print('halo world!')
    
greet = my_decorator(greet)
greet()

# 输出
wrapper of decorator!
hello world!

@my_decorator
def greet2():
    print('halo world2!')

greet2()

# 输出
wrapper of decorator!
hello world2!

这里my_decorator()为装饰器,将greet()包含在其中,改变了greet函数的行为,但是原函数greet并没变。不改变原函数的情况下,改变函数的行为。

调用方法:

1、像greet函数中进行调用

greet = my_decorator(greet) greet()

2、像greet2函数中进行调用 @my_decorator

这里的@称之为语法糖

二、带有参数的装饰器

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print('wrapper of decorator!')
        func(*args, **kwargs)
    return wrapper

@my_decorator
def greet(message):
    print(message)
    
greet('halo world!')

# 输出
wrapper of decorator!
halo world!

三、带有自定义参数的装饰器

举例:如果想让一个函数执行多次,可以写成

def repeat(num):
    def my_decorator(func):
        def wrapper(*args, **kwargs):
            for i in range(num):
                print('wrapper of decorator')
                func(*args, **kwargs)
        return wrapper
    return my_decorator


@repeat(4)
def greet(message):
    print(message)

greet('hello world')

# 输出:
wrapper of decorator
hello world
wrapper of decorator
hello world
wrapper of decorator
hello world
wrapper of decorator
hello world

四、原函数的元信息

greet.__name__
## 输出
wrapper

以上可知,原函数元信息改变,greet函数被wrapper函数取代

解决:采用内置装饰器@functools.wraps(func),将原函数的元信息拷贝到对应装饰器函数

import functools

def my_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print('wrapper of decorator!')
        func(*args, **kwargs)
    return wrapper

@my_decorator
def greet(message):
    print(message)
    
greet.__name__

# 输出
'greet'

五、类装饰器

主要依赖于函数_call_()

import time

class TimeCount:
    def __init__(self, func):
        self.func = func
     
    def __call__(self, *args, **kwargs):
        start_time = time.time()
        self.func()
        end_time = time.time()
        print(f'执行函数时间为:{start_time-end_time}')

@TimeCount
def greet():
    time.sleep(2)
    
greet()

六、装饰器嵌套

@decorator1
@decorator2
@decorator3
def func():
    ...

执行顺序:从里向外

decorator1(decorator2(decorator3(func)))
import functools

def my_decorator1(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print('execute decorator1')
        func(*args, **kwargs)
    return wrapper


def my_decorator2(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print('execute decorator2')
        func(*args, **kwargs)
    return wrapper


@my_decorator1
@my_decorator2
def greet(message):
    print(message)


greet('hello world')

# 输出
execute decorator1
execute decorator2
hello world

七、应用场景

身份认证、日志、缓存、输入合法性检查等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值