深入解析Python装饰器从入门到精通的实用指南

装饰器基础:功能与概念

装饰器是Python中一项强大的功能,允许我们在不修改原始函数代码的情况下,为函数或方法添加额外的功能。装饰器本质上是一个接受函数作为参数并返回一个新函数的可调用对象。这种编程模式遵循开放封闭原则,即对扩展开放,对修改封闭。理解装饰器的核心在于认识到函数在Python中是一等对象,可以作为参数传递、从函数返回,并分配给变量。

装饰器的基本语法与实现

Python装饰器使用@符号作为语法糖,将其放置在函数定义之前。最基本的装饰器形式是一个外层函数嵌套一个内层函数。外层函数接收被装饰函数作为参数,内层函数通常称为包装函数,它负责执行装饰逻辑并调用原始函数。

简单装饰器示例

以下是一个简单的装饰器示例,它记录函数的执行时间:

import timedef timer_decorator(func):    def wrapper(args, kwargs):        start_time = time.time()        result = func(args, kwargs)        end_time = time.time()        print(f{func.__name__} executed in {end_time - start_time} seconds)        return result    return wrapper@timer_decoratordef example_function():    time.sleep(2)    return Doneresult = example_function()

带参数的装饰器

有时我们需要装饰器本身能够接受参数,这就需要再嵌套一层函数。最外层函数接收装饰器参数,中间层接收被装饰函数,最内层实现装饰逻辑。

参数化装饰器示例

下面是一个带参数的装饰器示例,它可以指定重复执行函数的次数:

def repeat(num_times):    def decorator_repeat(func):        def wrapper(args, kwargs):            for _ in range(num_times):                result = func(args, kwargs)            return result        return wrapper    return decorator_repeat@repeat(num_times=3)def greet(name):    print(fHello {name})greet(World)

类装饰器

除了函数装饰器,Python还支持类装饰器。类装饰器通过实现__call__方法使类实例可调用,从而作为装饰器使用。类装饰器通常更适用于需要维护状态的装饰场景。

类装饰器实现

以下是一个类装饰器的示例,它跟踪函数被调用的次数:

class CountCalls:    def __init__(self, func):        self.func = func        self.num_calls = 0    def __call__(self, args, kwargs):        self.num_calls += 1        print(fCall {self.num_calls} of {self.func.__name__})        return self.func(args, kwargs)@CountCallsdef say_hello():    print(Hello!)say_hello()say_hello()

内置装饰器:property、staticmethod和classmethod

Python提供了几个内置装饰器,它们为面向对象编程提供了重要的功能。@property装饰器允许将方法作为属性访问,@staticmethod定义不需要访问实例或类的静态方法,@classmethod定义操作类而非实例的类方法。

内置装饰器应用

下面是这些内置装饰器的使用示例:

class MyClass:    def __init__(self, value):        self._value = value    @property    def value(self):        return self._value    @value.setter    def value(self, new_value):        self._value = new_value    @classmethod    def from_string(cls, string):        return cls(int(string))    @staticmethod    def is_integer(num):        return isinstance(num, int)

装饰器堆叠与执行顺序

多个装饰器可以堆叠在一个函数上,它们按照从下到上的顺序执行。了解装饰器的执行顺序对于正确使用复杂装饰器组合至关重要。

装饰器堆叠示例

以下示例展示了两个装饰器的堆叠使用:

def decorator1(func):    def wrapper():        print(Decorator 1)        func()    return wrapperdef decorator2(func):    def wrapper():        print(Decorator 2)        func()    return wrapper@decorator1@decorator2def say_hello():    print(Hello!)say_hello()# 输出:# Decorator 1# Decorator 2# Hello!

functools.wraps保护元数据

使用装饰器时,原始函数的元数据(如函数名、文档字符串等)会被包装函数覆盖。functools.wraps装饰器可以解决这个问题,它将原始函数的元数据复制到包装函数中。

使用functools.wraps

下面是在装饰器中使用functools.wraps的示例:

from functools import wrapsdef my_decorator(func):    @wraps(func)    def wrapper(args, kwargs):        Wrapper function docstring        print(Something is happening before the function is called.)        return func(args, kwargs)    return wrapper@my_decoratordef example():    Example function docstring    print(Hello from example!)print(example.__name__)  # 输出: exampleprint(example.__doc__)   # 输出: Example function docstring

装饰器在实际项目中的应用

装饰器在实际开发中有广泛的应用场景,包括但不限于:权限验证、日志记录、性能测试、事务处理、缓存结果和输入验证等。合理使用装饰器可以大大提高代码的可读性、可维护性和可复用性。

缓存装饰器示例

以下是一个简单的缓存装饰器实现,它可以存储函数的结果以避免重复计算:

from functools import wrapsdef cache(func):    cached_results = {}    @wraps(func)    def wrapper(args):        if args in cached_results:            return cached_results[args]        result = func(args)        cached_results[args] = result        return result    return wrapper@cachedef fibonacci(n):    if n < 2:        return n    return fibonacci(n-1) + fibonacci(n-2)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值