在 Python 中,装饰器是一种非常强大的工具,它可以在不修改原有代码的情况下,为函数、方法或类添加额外的功能。本文将深入探讨 Python 装饰器的高级用法,展示其在不同场景下的灵活性和强大功能。
一、装饰器简介
装饰器是一个函数,它接受一个函数作为参数,并返回一个新的函数。这个新函数通常会在调用原始函数之前或之后执行一些额外的操作。装饰器的语法如下:
@decorator_function
def original_function():
pass
在这个例子中,decorator_function
是一个装饰器函数,它会在original_function
被调用之前或之后执行一些操作。
二、简单装饰器示例
以下是一个简单的装饰器示例,它在函数被调用前后打印一些消息:
def my_decorator(func):
def wrapper():
print("Before function call")
func()
print("After function call")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
在这个例子中,my_decorator
是一个装饰器函数,它接受一个函数作为参数,并返回一个新的函数wrapper
。当say_hello
函数被调用时,实际上是调用了wrapper
函数,它会在调用原始函数say_hello
之前和之后打印一些消息。
三、高级用法
-
带参数的装饰器
-
装饰器也可以接受参数。这可以让你根据不同的参数来定制装饰器的行为。以下是一个带参数的装饰器示例:
def repeat(n): def decorator(func): def wrapper(*args, **kwargs): for _ in range(n): func(*args, **kwargs) return wrapper return decorator @repeat(3) def greet(): print("Hello!") greet()
在这个例子中,
repeat
是一个装饰器工厂函数,它接受一个参数n
,并返回一个装饰器函数。这个装饰器函数会将原始函数重复执行n
次。
-
-
装饰器的堆叠
-
多个装饰器可以堆叠在一起,依次应用于一个函数。以下是一个装饰器堆叠的示例:
def decorator1(func): def wrapper(): print("Decorator 1 before") func() print("Decorator 1 after") return wrapper def decorator2(func): def wrapper(): print("Decorator 2 before") func() print("Decorator 2 after") return wrapper @decorator1 @decorator2 def say_hello(): print("Hello!") say_hello()
在这个例子中,
say_hello
函数首先被decorator2
装饰,然后被decorator1
装饰。当say_hello
函数被调用时,装饰器会按照堆叠的顺序依次执行。
-
-
装饰类方法
-
装饰器不仅可以用于函数,还可以用于类方法。以下是一个装饰类方法的示例:
def timing_decorator(func): def wrapper(self, *args, **kwargs): import time start_time = time.time() result = func(self, *args, **kwargs) end_time = time.time() print(f"Function {func.__name__} took {end_time - start_time} seconds.") return result return wrapper class MyClass: def __init__(self): self.data = [1, 2, 3, 4, 5] @timing_decorator def process_data(self): for item in self.data: print(item) obj = MyClass() obj.process_data()
在这个例子中,
timing_decorator
装饰器被应用于MyClass
类的process_data
方法。它会测量方法的执行时间,并打印出执行时间的信息。
-
-
类作为装饰器
-
类也可以作为装饰器。当一个类被用作装饰器时,它的
__init__
方法会接受被装饰的函数作为参数,而它的__call__
方法会在函数被调用时执行。以下是一个类作为装饰器的示例:class MyDecorator: def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): print("Before function call") result = self.func(*args, **kwargs) print("After function call") return result @MyDecorator def add(a, b): return a + b print(add(3, 4))
在这个例子中,
MyDecorator
类被用作装饰器。当add
函数被调用时,MyDecorator
类的__call__
方法会在add
函数被调用之前和之后执行一些操作。
-
四、实际应用场景
-
日志记录
-
装饰器可以用于记录函数的调用信息,例如输入参数、输出结果和执行时间等。这对于调试和性能分析非常有用。
def log_decorator(func): def wrapper(*args, **kwargs): print(f"Calling function {func.__name__} with args {args} and kwargs {kwargs}") result = func(*args, **kwargs) print(f"Function {func.__name__} returned {result}") return result return wrapper @log_decorator def multiply(a, b): return a * b multiply(3, 4)
-
-
性能测量
-
装饰器可以用于测量函数的执行时间,以便优化代码性能。
def timing_decorator(func): def wrapper(*args, **kwargs): import time start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f"Function {func.__name__} took {end_time - start_time} seconds.") return result return wrapper @timing_decorator def slow_function(): import time time.sleep(2) slow_function()
-
-
权限控制
-
装饰器可以用于实现权限控制,确保只有授权的用户才能调用某些函数。
def permission_required(permission): def decorator(func): def wrapper(user, *args, **kwargs): if user.has_permission(permission): return func(user, *args, **kwargs) else: raise PermissionError(f"User {user} does not have permission to call {func.__name__}") return wrapper return decorator class User: def __init__(self, name, permissions): self.name = name self.permissions = permissions def has_permission(self, permission): return permission in self.permissions @permission_required("admin") def delete_user(user): print(f"Deleting user {user.name}") user1 = User("Alice", ["read", "write"]) user2 = User("Bob", ["admin"]) delete_user(user1) delete_user(user2)
-
五、总结
Python 装饰器是一种非常强大的工具,它可以在不修改原有代码的情况下,为函数、方法或类添加额外的功能。通过掌握装饰器的高级用法,你可以在日志记录、性能测量、权限控制等方面提高代码的可维护性和可扩展性。装饰器的灵活性和强大功能使得它们在 Python 编程中得到了广泛的应用。
标签:__,return,Python,代码,func,time,装饰,def From: https://blog.csdn.net/liuhailong0511/article/details/142457793