想象你是一个繁忙厨房里的厨师。如果你愿意的话,你有一个食谱——一个函数。随着时间的推移,您会发现大多数菜肴在上桌前都需要淋上一点橄榄油、少许盐或撒上香草。与其手动为每道菜添加这些最后的修饰,有一个自动应用它们的助手不是很方便吗?这正是 Python 装饰器可以为您的代码做的事情——以优雅、可重用且富有表现力的方式添加功能。
在本文中,我们将探索高级 Python 装饰器的世界。我们将超越基础知识,深入研究参数化装饰器、可堆叠装饰器,甚至带有类的装饰器。我们还将重点介绍最佳实践和要避免的陷阱。准备好?开始做饭吧!
在深入探讨之前,让我们回顾一下基础知识。 Python 中的装饰器只是一个函数,它接受另一个函数(或方法)作为参数,对其进行扩充,然后返回一个新函数。这是一个例子:
# Basic decorator example def simple_decorator(func): def wrapper(*args, **kwargs): print(f"Calling {func.__name__}...") result = func(*args, **kwargs) print(f"{func.__name__} finished.") return result return wrapper @simple_decorator def say_hello(): print("Hello, world!") say_hello()
输出:
Calling say_hello... Hello, world! say_hello finished.
现在,让我们进入高级用例。
有时,装饰器需要接受自己的参数。例如,如果我们想要一个装饰器来记录不同级别的消息(信息、调试、错误)怎么办?
# Parameterized decorator example def log(level): def decorator(func): def wrapper(*args, **kwargs): print(f"[{level}] Calling {func.__name__}...") result = func(*args, **kwargs) print(f"[{level}] {func.__name__} finished.") return result return wrapper return decorator @log("INFO") def process_data(): print("Processing data...") process_data()
输出:
[INFO] Calling process_data... Processing data... [INFO] process_data finished.
这种分层结构(返回装饰器的函数)是创建灵活的参数化装饰器的关键。
Python 允许将多个装饰器应用于单个函数。让我们创建两个装饰器并将它们堆叠起来。
# Stackable decorators def uppercase(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) return result.upper() return wrapper def exclaim(func): def wrapper(*args, **kwargs): result = func(*args, **kwargs) return result + "!!!" return wrapper @uppercase @exclaim def greet(): return "hello" print(greet())
输出:
HELLO!!!
这里,装饰器以自下而上的方式应用:@exclaim 包装问候,@uppercase 包装结果。
Python 的一个鲜为人知的功能是类可以用作装饰器。当您需要维护状态时,这特别有用。
# Class-based decorator class CountCalls: def __init__(self, func): self.func = func self.call_count = 0 def __call__(self, *args, **kwargs): self.call_count += 1 print(f"Call {self.call_count} to {self.func.__name__}") return self.func(*args, **kwargs) @CountCalls def say_hello(): print("Hello!") say_hello() say_hello()
输出:
Call 1 to say_hello Hello! Call 2 to say_hello Hello!
这里,call 方法使类能够像函数一样运行,从而允许它无缝地包装目标函数。
装饰器与类中的方法一样有效。然而,正确处理自我是至关重要的。
# Method decorator example def log_method(func): def wrapper(self, *args, **kwargs): print(f"Method {func.__name__} called on {self}") return func(self, *args, **kwargs) return wrapper class Greeter: @log_method def greet(self, name): print(f"Hello, {name}!") obj = Greeter() obj.greet("Alice")
输出:
Method greet called on <__main__.Greeter object at 0x...> Hello, Alice!
有时,您需要将装饰器与资源管理集成。例如,让我们创建一个装饰器来对函数的执行进行计时。
import time # Timing decorator def time_it(func): def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(f"{func.__name__} took {end - start:.2f} seconds") return result return wrapper @time_it def slow_function(): time.sleep(2) print("Done sleeping!") slow_function()
输出:
# Basic decorator example def simple_decorator(func): def wrapper(*args, **kwargs): print(f"Calling {func.__name__}...") result = func(*args, **kwargs) print(f"{func.__name__} finished.") return result return wrapper @simple_decorator def say_hello(): print("Hello, world!") say_hello()
与装饰器合作时,保持可读性和可维护性至关重要。这里有一些提示:
Calling say_hello... Hello, world! say_hello finished.
彻底测试:装饰器可能会引入微妙的错误,尤其是在链接多个装饰器时。
文档装饰器:清楚地记录每个装饰器的作用及其预期参数。
避免过度使用:虽然装饰器很强大,但过度使用它们会使代码难以理解。
装饰器是 Python 最具表现力的功能之一。它们允许您以干净、可重用的方式扩展和修改行为。从参数化装饰器到基于类的实现,可能性是无限的。当你磨练你的技能时,你会发现自己利用装饰器来编写更干净、更Pythonic的代码——也许,就像一位伟大的厨师一样,在你制作的每一个菜谱中创造出你的标志性风格。
注:AI辅助内容
以上是高级 Python 装饰器:提升您的代码的详细内容。更多信息请关注PHP中文网其他相关文章!