解析 Python 装饰器高级用法六项

开发 后端
本文通过六个高级用法详细探讨了Python装饰器的强大功能,通过实际的代码示例和逐步引导,希望读者能够深入理解装饰器的原理和应用。

在Python编程中,装饰器(Decorators)是一种强大且灵活的工具,它允许你在不修改原有函数或方法定义的情况下,为其添加新的功能。装饰器是高级主题,但掌握它后,你将能写出更加简洁和可重用的代码。本文将深入探讨Python装饰器的6项高级用法,通过详细的例子和逐步的引导,帮助初学者理解和掌握这一强大特性。

1. 带参数的装饰器

装饰器本身也可以接受参数,这使得装饰器更加灵活。我们可以通过定义一个外层的函数来传递参数给装饰器。

def my_decorator(arg):  
    def wrapper(func):  
        def inner(*args, **kwargs):  
            print(f"Decorator argument: {arg}")  
            return func(*args, **kwargs)  
        return inner  
    return wrapper  

@my_decorator("Hello, World!")  
def say_hello():  
    print("Hello from the function!")  

say_hello()  

输出:

Decorator argument: Hello, World!  
Hello from the function!  

代码解释:

  • my_decorator 是一个接受参数的装饰器工厂。
  • wrapper 是实际的装饰器,它接受一个函数 func 作为参数。
  • inner 是实际调用原始函数并添加额外功能的包装函数。

2. 类装饰器

除了函数装饰器,Python还支持类装饰器。类装饰器允许你使用类来定义装饰器逻辑。

class MyDecorator:  
    def __init__(self, func):  
        self.func = func  

    def __call__(self, *args, **kwargs):  
        print("Before the function is called.")  
        result = self.func(*args, **kwargs)  
        print("After the function is called.")  
        return result  

@MyDecorator  
def greet(name):  
    print(f"Hello, {name}!")  

greet("Alice")  

输出:

Before the function is called.  
Hello, Alice!  
After the function is called.  

代码解释:

  • MyDecorator 是一个类,它的 __init__ 方法接受一个函数 func。
  • __call__ 方法使得类的实例可以像函数一样被调用。

3. 装饰器链

你可以将多个装饰器应用于同一个函数,这些装饰器会按照从外到内的顺序被调用。

def decorator_one(func):  
    def wrapper(*args, **kwargs):  
        print("Decorator One")  
        return func(*args, **kwargs)  
    return wrapper  

def decorator_two(func):  
    def wrapper(*args, **kwargs):  
        print("Decorator Two")  
        return func(*args, **kwargs)  
    return wrapper  

@decorator_one  
@decorator_two  
def my_function():  
    print("My Function")  

my_function()  

输出:

Decorator One  
Decorator Two  
My Function  

代码解释:

  • decorator_one 和 decorator_two 是两个装饰器。
  • @decorator_one 和 @decorator_two 按照从外到内的顺序应用于 my_function。

4. 装饰器中的装饰器

装饰器内部也可以嵌套使用其他装饰器,从而组合多个装饰器的功能。

def decorator_a(func):  
    def wrapper(*args, **kwargs):  
        print("Decorator A")  
        return func(*args, **kwargs)  
    return wrapper  

def decorator_b(func):  
    def wrapper(*args, **kwargs):  
        print("Decorator B")  
        return func(*args, **kwargs)  
    return wrapper  

def combine_decorators(func):  
    return decorator_a(decorator_b(func))  

@combine_decorators  
def my_function():  
    print("My Function")  

my_function()  

输出:

Decorator A  
Decorator B  
My Function  

代码解释:

  • combine_decorators 是一个装饰器,它将 decorator_a 和 decorator_b 组合在一起。

5. 装饰器与异步函数

Python 3.5 引入了异步编程的支持,装饰器也可以用于异步函数。

import asyncio  

def async_decorator(func):  
    async def wrapper(*args, **kwargs):  
        print("Before the async function is called.")  
        await func(*args, **kwargs)  
        print("After the async function is called.")  
    return wrapper  

@async_decorator  
async def async_greet(name):  
    await asyncio.sleep(1)  
    print(f"Hello, {name}!")  

async def main():  
    await async_greet("Bob")  

asyncio.run(main())  

输出:

Before the async function is called.  
Hello, Bob!  
After the async function is called.  

代码解释:

  • async_decorator 是一个装饰器,用于异步函数。
  • async_greet 是一个异步函数,通过 await 关键字等待异步操作完成。

6. 装饰器与属性

在类的方法上应用装饰器时,可以访问类的属性和其他方法。

class MyClass:  
    def __init__(self):  
        self.count = 0  

    def decorator(self, func):  
        def wrapper(*args, **kwargs):  
            self.count += 1  
            print(f"Count before call: {self.count}")  
            result = func(*args, **kwargs)  
            print(f"Count after call: {self.count}")  
            return result  
        return wrapper  

    @decorator  
    def my_method(self):  
        print("Method is called")  

obj = MyClass()  
obj.my_method()  
obj.my_method()  

输出:

Count before call: 1  
Method is called  
Count after call: 2  
Count before call: 3  
Method is called  
Count after call: 4  

代码解释:

  • MyClass 类中有一个装饰器 decorator,它访问类的 count 属性。
  • @decorator 应用于 my_method,每次调用 my_method 时都会更新 count 属性。

实战案例:日志记录装饰器

在实际开发中,日志记录是一个常见的需求。我们可以编写一个装饰器来自动记录函数的调用情况,包括调用时间、参数和返回值。

import time  

def log_decorator(func):  
    def wrapper(*args, **kwargs):  
        start_time = time.time()  
        print(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}")  
        result = func(*args, **kwargs)  
        end_time = time.time()  
        print(f"{func.__name__} returned {result} in {end_time - start_time:.4f} seconds")  
        return result  
    return wrapper  

@log_decorator  
def complex_calculation(a, b):  
    time.sleep(2)  # Simulate a long-running calculation  
    return a + b  

result = complex_calculation(3, 4)  
print(f"Final result: {result}")  

输出:

Calling complex_calculation with args: (3, 4), kwargs: {}  
complex_calculation returned 7 in 2.0021 seconds  
Final result: 7  

案例分析:- log_decorator 装饰器记录了 complex_calculation 函数的调用时间、参数和返回值。- 这种方式非常适用于调试和性能分析,而不需要修改原始函数的代码。

总结

本文通过六个高级用法详细探讨了Python装饰器的强大功能,包括带参数的装饰器、类装饰器、装饰器链、装饰器中的装饰器、装饰器与异步函数以及装饰器与属性的结合使用。通过实际的代码示例和逐步引导,希望读者能够深入理解装饰器的原理和应用。

责任编辑:赵宁宁 来源: 手把手PythonAI编程
相关推荐

2010-09-26 09:04:44

2021-06-01 07:19:58

Python函数装饰器

2021-08-19 16:08:24

高级威胁网络安全网络攻击

2010-09-14 21:47:05

2012-04-29 11:24:09

iPhone

2010-08-31 15:03:18

网络钓鱼

2024-01-03 14:07:06

技术ChatGPTIT

2015-10-21 13:10:49

2016-09-02 14:38:55

物联网

2020-05-19 10:20:19

物联网新商业技术

2013-08-27 10:27:14

2021-04-14 10:59:28

JavaScript 前端this

2016-09-30 10:30:12

2017-04-25 14:12:13

华为

2012-07-10 09:39:28

2016-12-06 08:20:27

科技新闻早报

2015-10-10 09:45:28

AWSAWS re:Inve云迁移

2017-02-24 07:23:00

深度学习方向预测

2016-06-07 09:23:05

浏览器技巧快捷键
点赞
收藏

51CTO技术栈公众号