Python(18)装饰器

        在 Python 编程领域,装饰器是一项功能强大且灵活的特性,它能在不修改原有函数或类代码的基础上,动态地为它们添加新功能。通过丰富的代码示例,深入学习 Python 装饰器知识,方便日后复习回顾。

一、装饰器基础概念

1.1 装饰器的定义

        装饰器本质上是一个函数,它以另一个函数作为参数,并返回一个新函数或对原函数进行修改。在 Python 中,使用@decorator_name语法将装饰器应用到函数或方法上。例如:

def decorator_function(original_function):
    def wrapper():
        print("在原函数执行前添加的操作")
        original_function()
        print("在原函数执行后添加的操作")
    return wrapper


@decorator_function
def target_function():
    print("这是原函数的操作")


target_function()

        在上述代码中,decorator_function是装饰器函数,它接受target_function作为参数,并返回wrapper函数。@decorator_function语法将target_function传递给decorator_function,之后调用target_function时,实际调用的是wrapper函数,从而实现了在原函数前后添加额外操作的功能。运行代码后,输出结果为:

在原函数执行前添加的操作
这是原函数的操作
在原函数执行后添加的操作

1.2 装饰器的工作原理

        当使用@decorator_name装饰函数时,Python 会自动将被装饰的函数作为参数传递给装饰器函数,装饰器函数返回的新函数会替换原来的函数。可以将这个过程理解为:

def target_function():
    print("这是原函数的操作")


target_function = decorator_function(target_function)

        这种机制使得装饰器能够在不改变原函数代码的情况下,对函数的行为进行扩展。


二、装饰器的应用场景

2.1 日志记录

        在函数执行前后记录相关信息,方便调试和追踪。例如:

def log_function_call(func):
    def wrapper(*args, **kwargs):
        print(f"调用函数 {func.__name__},参数为:{args}, {kwargs}")
        result = func(*args, **kwargs)
        print(f"函数 {func.__name__} 执行完毕,返回值为:{result}")
        return result
    return wrapper


@log_function_call
def add_numbers(a, b):
    return a + b


add_numbers(3, 5)

运行代码后,会输出函数调用和返回的相关信息:

调用函数 add_numbers,参数为:(3, 5), {}
函数 add_numbers 执行完毕,返回值为:8

2.2 性能分析

        测量函数的执行时间,用于优化代码性能。例如:

import time


def measure_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"函数 {func.__name__} 执行时间为:{end_time - start_time} 秒")
        return result
    return wrapper


@measure_time
def complex_calculation():
    time.sleep(2)  # 模拟复杂计算
    return 42


complex_calculation()

        运行代码后,会输出函数的执行时间:

函数 complex_calculation 执行时间为:2.000000 秒(实际输出的时间会因系统差异略有不同)

2.3 权限控制

        限制对某些函数的访问权限。例如:

def check_permission(func):
    def wrapper():
        # 假设这里通过某种方式检查权限,比如判断用户是否登录
        is_logged_in = True  # 模拟登录状态
        if is_logged_in:
            return func()
        else:
            print("权限不足,无法访问该函数")
    return wrapper


@check_permission
def sensitive_operation():
    print("执行敏感操作")


sensitive_operation()

        如果is_logged_inFalse,运行代码后会输出 “权限不足,无法访问该函数”;为True时,则正常执行函数。


三、装饰器的不同形式

3.1 带参数的装饰器

        装饰器不仅可以装饰带参数的函数,自身也可以接受参数。例如:

def repeat(num_times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                func(*args, **kwargs)
        return wrapper
    return decorator


@repeat(3)
def say_hello():
    print("Hello!")


say_hello()

        这里repeat是一个装饰器工厂函数,它接受num_times参数,返回一个装饰器decorator@repeat(3)表示将say_hello函数重复执行 3 次,运行代码后会输出 3 次 “Hello!”。

3.2 类装饰器

        类也可以作为装饰器使用,通过定义__call__方法来实现。例如:

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

    def __call__(self, *args, **kwargs):
        print("在类装饰器中,执行原函数前的操作")
        result = self.func(*args, **kwargs)
        print("在类装饰器中,执行原函数后的操作")
        return result


@ClassDecorator
def decorated_function():
    print("这是被类装饰器装饰的函数")


decorated_function()

        在上述代码中,ClassDecorator类作为装饰器,当调用decorated_function时,会执行ClassDecorator类中__call__方法里的额外操作,输出结果为:

在类装饰器中,执行原函数前的操作
这是被类装饰器装饰的函数
在类装饰器中,执行原函数后的操作

3.3 多个装饰器堆叠

        多个装饰器可以堆叠使用,它们按照从下到上的顺序依次应用。例如:

def decorator1(func):
    def wrapper():
        print("Decorator 1 执行前")
        func()
        print("Decorator 1 执行后")
    return wrapper


def decorator2(func):
    def wrapper():
        print("Decorator 2 执行前")
        func()
        print("Decorator 2 执行后")
    return wrapper


@decorator1
@decorator2
def target():
    print("这是目标函数")


target()

        运行代码后,输出结果为:

Decorator 1 执行前
Decorator 2 执行前
这是目标函数
Decorator 2 执行后
Decorator 1 执行后

四、Python 内置装饰器

4.1 @staticmethod

        将方法定义为静态方法,不需要实例化类即可调用。例如:

class MyClass:
    @staticmethod
    def static_method():
        print("这是一个静态方法")


MyClass.static_method()

        运行代码后,直接通过类名调用static_method方法,输出 “这是一个静态方法”。

4.2 @classmethod

        将方法定义为类方法,第一个参数是类本身(通常命名为cls)。例如:

class MyClass:
    @classmethod
    def class_method(cls):
        print(f"这是 {cls.__name__} 的类方法")


MyClass.class_method()

        运行代码后,同样通过类名调用class_method方法,输出 “这是 MyClass 的类方法”。

4.3 @property

        将方法转换为属性,使其可以像属性一样访问。例如:

class MyClass:
    def __init__(self):
        self._name = ""

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value


obj = MyClass()
obj.name = "Alice"
print(obj.name)

        在上述代码中,通过@property装饰器将name方法转换为属性,实现了像访问属性一样访问和设置name的值。


五、总结

        Python 装饰器为代码的功能扩展提供了一种优雅且高效的方式,无论是日志记录、性能分析、权限控制,还是与内置装饰器的结合使用,都能显著提升代码的质量和可维护性。通过深入学习装饰器的原理、应用场景和不同形式,在实际编程中可以根据需求灵活运用,编写出更加简洁、健壮的代码。希望这篇博客能帮助你更好地复习和巩固 Python 装饰器的知识,在编程实践中充分发挥其优势。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值