深入理解 Python 的装饰器
💖 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长。
🔍 博客内容包括:
- Java核心技术与微服务:涵盖Java基础、JVM、并发编程、Redis、Kafka、Spring等,帮助您全面掌握企业级开发技术。
- 大数据技术:涵盖Hadoop(HDFS)、Hive、Spark、Flink、Kafka、Redis、ECharts、Zookeeper等相关技术。
- 开发工具:分享常用开发工具(IDEA、Git、Mac、Alfred、Typora等)的使用技巧,提升开发效率。
- 数据库与优化:总结MySQL及其他常用数据库技术,解决实际工作中的数据库问题。
- Python与大数据:专注于Python编程语言的深度学习,数据分析工具(如Pandas、NumPy)和大数据处理技术,帮助您掌握数据分析、数据挖掘、机器学习等技术。
- 数据结构与算法:总结数据结构与算法的核心知识,提升编程思维,帮助您应对大厂面试挑战。
🌟 我的目标:持续学习与总结,分享技术心得与解决方案,和您一起探索技术的无限可能!在这里,我希望能与您共同进步,互相激励,成为更好的自己。
📣 欢迎订阅本专栏,与我一起在这个知识的海洋中不断学习、分享和成长!💻🚀
📍版权声明:本博客所有内容均为原创,遵循CC 4.0 BY-SA协议,转载请注明出处。
目录
一、什么是装饰器?
二、简单的装饰器示例
示例 1:打印日志
三、装饰器的原理
1. 函数即对象
2. 闭包
四、装饰器的高级用法
1. 为装饰器传递参数
2. 保留原函数的元数据
3. 装饰类方法
五、内置装饰器
1. @staticmethod
2. @classmethod
3. @property
六、多个装饰器的执行顺序
七、常见的装饰器应用场景
1. 权限验证
2. 性能分析
装饰器是 Python 中非常强大和灵活的功能。它可以在不改变函数定义的情况下,动态地为函数或方法添加新的功能。本文将带你深入理解装饰器的原理、用法以及一些高级技巧。
一、什么是装饰器?
装饰器本质上是一个函数,它接收一个函数作为参数,并返回一个增强后的函数。装饰器通常用来修改函数的行为,比如增加日志记录、访问控制或性能计时等。
装饰器的基本语法:
@decorator_function
def original_function():
pass
等价于:
def original_function():
pass
original_function = decorator_function(original_function)
二、简单的装饰器示例
示例 1:打印日志
def logger(func):
def wrapper(*args, **kwargs):
print(f"Calling function '{func.__name__}' with arguments {args} and {kwargs}")
result = func(*args, **kwargs)
print(f"Function '{func.__name__}' returned {result}")
return result
return wrapper
@logger
def add(a, b):
return a + b
add(3, 5)
输出:
Calling function 'add' with arguments (3, 5) and {}
Function 'add' returned 8
三、装饰器的原理
1. 函数即对象
在 Python 中,函数是一等公民,可以作为参数传递,也可以作为返回值。
2. 闭包
装饰器通常依赖闭包来保存上下文信息。闭包是指在嵌套函数中,内部函数引用了外部函数的变量。
示例:
def outer_function(message):
def inner_function():
print(message)
return inner_function
closure = outer_function("Hello, World!")
closure()
输出:
Hello, World!
四、装饰器的高级用法
1. 为装饰器传递参数
如果需要给装饰器传递参数,可以使用多层嵌套。
示例:
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(name):
print(f"Hello, {name}!")
greet("Alice")
输出:
Hello, Alice!
Hello, Alice!
Hello, Alice!
2. 保留原函数的元数据
使用 functools.wraps
可以保留被装饰函数的原始信息(如名称和文档字符串)。
示例:
from functools import wraps
def logger(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
@logger
def add(a, b):
"""Add two numbers."""
return a + b
print(add.__name__)
print(add.__doc__)
输出:
add
Add two numbers.
3. 装饰类方法
装饰器也可以用于类方法。
示例:
def logger(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
class MyClass:
@logger
def greet(self):
print("Hello from MyClass!")
obj = MyClass()
obj.greet()
输出:
Calling greet
Hello from MyClass!
五、内置装饰器
Python 提供了一些常用的内置装饰器:
1. @staticmethod
定义类的静态方法,与类实例无关。
class MyClass:
@staticmethod
def static_method():
print("This is a static method.")
MyClass.static_method()
2. @classmethod
定义类方法,可以访问类本身。
class MyClass:
@classmethod
def class_method(cls):
print(f"This is a class method from {cls}.")
MyClass.class_method()
3. @property
将方法变为属性。
class MyClass:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
obj = MyClass("Alice")
print(obj.name)
六、多个装饰器的执行顺序
当一个函数有多个装饰器时,它们的执行顺序是自下而上。
示例:
def decorator1(func):
def wrapper(*args, **kwargs):
print("Decorator 1")
return func(*args, **kwargs)
return wrapper
def decorator2(func):
def wrapper(*args, **kwargs):
print("Decorator 2")
return func(*args, **kwargs)
return wrapper
@decorator1
@decorator2
def greet():
print("Hello!")
greet()
输出:
Decorator 1
Decorator 2
Hello!
七、常见的装饰器应用场景
1. 权限验证
def requires_permission(permission):
def decorator(func):
def wrapper(user, *args, **kwargs):
if user.has_permission(permission):
return func(user, *args, **kwargs)
else:
print("Permission denied!")
return wrapper
return decorator
@requires_permission("admin")
def delete_user(user, username):
print(f"User {username} deleted.")
2. 性能分析
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} executed in {end - start:.2f} seconds")
return result
return wrapper
@timer
def compute():
time.sleep(2)
print("Computation done!")
compute()