Python装饰器基础教程,编写模块化的可维护代码

装饰器

装饰器是Python中一个强大而灵活的特性,允许在不修改原始函数或类定义的情况下,动态地修改或增强其行为。本节将深入探讨函数装饰器、类装饰器以及带参数的装饰器,展示如何使用装饰器来实现代码复用、函数注册、访问控制等功能。通过掌握装饰器的使用,可以编写出更加模块化和可维护的代码。

函数装饰器

函数装饰器是一种可调用对象,它接受一个函数作为输入,并返回一个新的函数。装饰器通常用于在不修改原始函数代码的情况下,添加额外的功能,如日志记录、性能测量或访问控制。

以下是一个简单的函数装饰器示例:

import time

def timing_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:.2f} seconds to execute.")
        return result
    return wrapper

@timing_decorator
def slow_function():
    time.sleep(2)
    print("Function executed")

slow_function()

在这个例子中,timing_decorator 是一个装饰器,它包装了原始函数并添加了计时功能。@timing_decorator 语法等同于 slow_function = timing_decorator(slow_function)

装饰器也可以用于实现函数注册:

registry = []

def register(func):
    registry.append(func)
    return func

@register
def foo():
    print("foo")

@register
def bar():
    print("bar")

print(registry)  # 输出: [<function foo at ...>, <function bar at ...>]

这个例子展示了如何使用装饰器将函数添加到一个注册表中,这在插件系统或命令分发器中非常有用。

类装饰器

类装饰器与函数装饰器类似,但它们作用于类定义。类装饰器接收一个类作为参数,并返回一个新的类或修改后的原始类。

以下是一个类装饰器的示例:

def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance

@singleton
class Database:
    def __init__(self):
        print("Initializing database connection")

# 使用装饰后的类
db1 = Database()
db2 = Database()
print(db1 is db2)  # 输出: True

在这个例子中,singleton 装饰器确保一个类只有一个实例。无论创建多少次 Database 对象,都会返回同一个实例。

带参数的装饰器

有时需要创建可以接受参数的装饰器。这可以通过在装饰器外部再包装一层函数来实现。

以下是一个带参数的装饰器示例:

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

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

greet("Alice")

在这个例子中,repeat 是一个可以接受参数的装饰器。它返回一个装饰器函数,该函数然后包装被装饰的函数。@repeat(3) 语法告诉Python使用 repeat(3) 的结果作为装饰器。

装饰器也可以用于参数验证:

def validate_types(*types):
    def decorator(func):
        def wrapper(*args):
            if len(args) != len(types):
                raise ValueError("Invalid number of arguments")
            for arg, type_ in zip(args, types):
                if not isinstance(arg, type_):
                    raise TypeError(f"Argument {arg} is not of type {type_}")
            return func(*args)
        return wrapper
    return decorator

@validate_types(int, int)
def add(x, y):
    return x + y

print(add(1, 2))  # 输出: 3
# print(add(1, "2"))  # 引发 TypeError

这个例子展示了如何使用带参数的装饰器来实现函数参数的类型检查。

装饰器是Python中一个强大的特性,允许以非侵入式的方式修改或增强函数和类的行为。函数装饰器可用于添加额外功能,如日志记录、性能测量或访问控制。类装饰器可以修改类的行为或结构。带参数的装饰器提供了更大的灵活性,允许根据需要配置装饰器的行为。通过掌握装饰器的使用,可以编写出更加模块化、可复用和易于维护的代码。装饰器在很多Python框架和库中被广泛使用,理解和使用装饰器是成为高级Python开发者的重要一步。

THE END