文章目录
- Python装饰器解析
- 什么是Python装饰器
- 基础理解
- 如何创建装饰器(关键点:高阶函数、嵌套函数)
- 创建基础装饰器
- 使用装饰器
- 使用示例
- 装饰器的返回值
- 参数化装饰器
- 创建参数化装饰器
- 语法示例
- 使用示例
- 类装饰器
- 创建类装饰器
- 语法示例
- 使用示例
Python装饰器解析
Python装饰器是一个非常强大的工具,可以帮助我们以简洁的方式修改函数和类的行为。本文将对Python装饰器进行深入探讨,包括装饰器的基本概念、创建装饰器、使用装饰器以及如何处理更复杂的装饰器用例。
什么是Python装饰器
在Python中,装饰器基本上是一个函数,它接受一个函数作为输入并返回一个新的函数。
基础理解
def my_decorator(func):def wrapper():print("Before function execution")func()print("After function execution")return wrapperdef say_hello():print("Hello!")say_hello_ = my_decorator(say_hello)
say_hello_()
运行结果:
这里,my_decorator就是一个装饰器。它接收一个函数say_hello作为输入,并返回了一个新的函数wrapper。
如何创建装饰器(关键点:高阶函数、嵌套函数)
Python装饰器的创建有两个关键要点:1) 高阶函数;2) 嵌套函数。高阶函数表示函数可以接受其他函数作为参数,或者返回一个函数作为结果。嵌套函数表示在一个函数内部可以定义另一个函数。
创建基础装饰器
def my_decorator(func):def wrapper():print("Before function execution")func()print("After function execution")return wrapper
使用装饰器
在Python中,使用装饰器非常简单,只需要在你想要“装饰”的函数上方添加@装饰器名即可。
使用示例
@my_decorator
def say_hello():print("Hello!")say_hello()
这段代码的执行效果与前面通过直接调用装饰器并将其赋值给原函数的方式是完全相同的。
装饰器的返回值
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time
encoding = 'utf-8'def timer_decorator(func):def wrapper(*args, **kwargs):start_time = time.time()result = func(*args, **kwargs)end_time = time.time()print(f"{func.__name__} took {end_time - start_time} seconds to run.")return resultreturn wrapper@timer_decorator
def long_running_operation():time.sleep(2)return 'sleep complete'print(long_running_operation())
运行结果:
这里,timer_decorator
就是一个装饰器。它接收一个函数long_running_operation
作为输入,并返回了一个新的函数wrapper
。
参数化装饰器
在很多情况下,我们希望我们的装饰器能够接受参数,以便我们能够对其行为进行更细粒度的控制。这就引出了所谓的参数化装饰器。
创建参数化装饰器
语法示例
这个装饰器用来重复执行函数指定次数:
def repeat(num_times):def decorator_repeat(func):def wrapper(*args, **kwargs):for _ in range(num_times):func(*args, **kwargs)return wrapperreturn decorator_repeat
使用示例
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time
encoding = 'utf-8'def repeat(num_times):def decorator_repeat(func):def wrapper(*args, **kwargs):for _ in range(num_times):func(*args, **kwargs)return wrapperreturn decorator_repeat@repeat(3) # 表示要重复执行3次
def greet(name):print(f"Hello {name}")greet("Alice")
类装饰器
除了函数装饰器,Python还支持类装饰器。类装饰器主要依赖于函数__call__()
,每当你调用一个类的示例时,函数__call__()
就会被执行。
创建类装饰器
语法示例
下面这个类装饰器CountCalls的主要目的是跟踪某个函数被调用的次数。它通过覆盖__call__
方法来实现这一点,每当装饰的函数被调用时,就会增加num_calls计数器的值,并打印出该函数已被调用的次数:
class CountCalls:def __init__(self, func):self.func = funcself.num_calls = 0def __call__(self, *args, **kwargs):self.num_calls += 1print(f"Call {self.num_calls} of {self.func.__name__!r}")return self.func(*args, **kwargs)
使用示例
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time
encoding = 'utf-8'class CountCalls:def __init__(self, func):self.func = funcself.num_calls = 0def __call__(self, *args, **kwargs):self.num_calls += 1print(f"Call {self.num_calls} of {self.func.__name__!r}")return self.func(*args, **kwargs)@CountCalls
def say_hello(name):print(f"Hello, {name}")say_hello("Alice")
say_hello("Bob")
运行结果:
ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ
ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ ᅟᅠ