Python装饰器是一种强大的功能,用于修改或扩展函数或方法的行为。装饰器本质上是一个函数,它接受一个函数作为输入,并返回一个新的函数,通常是对输入函数的增强或修改。装饰器在代码中广泛用于日志记录、性能分析、验证、权限检查等方面,可以提高代码的可维护性和可复用性。
import datetime
# 定义一个装饰器函数
def info_log(func):
def wrapper():
print(datetime.datetime.now())
func()
print(datetime.datetime.now())
return wrapper
# 使用装饰器
@info_log
def say_hello():
print("Hello!")
# 调用被装饰的函数
say_hello()
在这个示例中,info_log
是一个装饰器函数,它接受一个函数 func
作为参数,并返回了一个新的函数 wrapper
。wrapper
函数在调用 func
之前和之后分别打印了一些信息。通过在 say_hello
函数上方使用 @info_log
,我们将 say_hello
函数装饰了起来,使其在调用时会执行额外的操作。
当运行上述代码时,输出将如下所示:
2023-10-08 22:31:01.191623
Hello!
2023-10-08 22:31:01.191623
这只是装饰器的一个简单示例。Python中有许多内置的装饰器,也可以创建自定义装饰器来满足特定需求。装饰器是Python中强大而灵活的工具,可用于各种编程任务。
它们在标准库中提供了有用的功能,包括:
@staticmethod
: 将一个方法装饰为静态方法。@classmethod
: 将一个方法装饰为类方法。@property
: 将一个方法装饰为属性,可以让方法像访问属性一样调用。@abstractmethod
: 用于定义抽象基类中的抽象方法,必须由子类实现。@abstractmethod
: 用于定义抽象基类中的抽象属性,必须由子类实现。@wraps
: 用于保留被装饰函数的元数据,通常在自定义装饰器中使用。@functools.lru_cache
: 用于实现缓存,可以缓存函数的计算结果以提高性能。
示例:
from functools import wraps
# 使用@property定义属性装饰器
class MyClass:
def __init__(self, value):
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, new_value):
self._value = new_value
# 使用@staticmethod定义静态方法
class MathUtils:
@staticmethod
def add(x, y):
return x + y
# 使用@classmethod定义类方法
class Date:
def __init__(self, day, month, year):
self.day = day
self.month = month
self.year = year
@classmethod
def from_string(cls, date_string):
day, month, year = map(int, date_string.split('-'))
return cls(day, month, year)
# 使用@abstractmethod定义抽象方法
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
# 使用@functools.lru_cache实现缓存
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
# 使用@wraps保留元数据
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
"""My Wrapper Docstring"""
return func(*args, **kwargs)
return wrapper
装饰器是Python中一种强大的编程工具,它用于修改或扩展函数或方法的行为,而无需修改它们的源代码。装饰器通常用于以下场景:
1. **日志记录**: 装饰器可以用于记录函数的调用信息、参数和返回值,以便进行调试和性能分析。
2. **权限控制**: 装饰器可以用于检查用户是否有足够的权限来执行特定操作,例如登录验证、角色检查等。
3. **性能优化**: 装饰器可以用于缓存函数的计算结果,以避免重复计算,提高性能。
4. **异常处理**: 装饰器可以用于捕获函数内部的异常并进行处理,以便进行错误处理或日志记录。
5. **事务管理**: 装饰器可以用于实现数据库事务管理,确保在一系列数据库操作中要么全部成功,要么全部失败。
6. **计时和统计**: 装饰器可以用于测量函数的执行时间,或统计函数的调用次数。
7. **单例模式**: 装饰器可以用于确保某个类只有一个实例。
8. **API路由**: 在Web框架中,装饰器可以用于将函数映射到特定的URL路由,实现API的路由功能。
9. **缓存**: 装饰器可以用于缓存函数的结果,以减少重复计算。
装饰器的概念非常灵活,它允许开发人员以声明性的方式来修改函数或方法的行为,而不需要修改它们的源代码。这提高了代码的可重用性和可维护性,使得代码更加模块化和清晰。
示例:
# 装饰器示例,记录函数调用日志
def log_function_call(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
print(f"Calling {func.__name__} with args={args} and kwargs={kwargs}")
return result
return wrapper
@log_function_call
def add(x, y):
return x + y
add(2, 3) # 输出:Calling add with args=(2, 3) and kwargs={}
在这个示例中,`log_function_call` 装饰器记录了 `add` 函数的调用信息,而不需要修改 `add` 函数的源代码。
一些常用的第三方装饰器。
1、Flask: Flask 是一个流行的 Python Web 框架,它提供了许多与 Web 开发相关的装饰器,如 @app.route
用于路由 URL,@app.before_request
和 @app.after_request
用于处理请求前和请求后的逻辑。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return 'Hello, World!'
if __name__ == '__main__':
app.run()
2、pytest: pytest 是一个流行的 Python 测试框架,它提供了多个装饰器,如 @pytest.fixture
用于创建测试夹具,@pytest.mark.parametrize
用于参数化测试等。
import pytest
@pytest.mark.parametrize("input, expected", [(1, 2), (2, 4), (3, 6)])
def test_multiply_by_two(input, expected):
result = input * 2
assert result == expected
@pytest.mark.skip(reason="Test not implemented yet")
def test_function_to_be_implemented():
assert True
@pytest.mark.xfail(reason="Expected to fail, but not a showstopper")
def test_expected_failure():
assert False
3、在 unittest 中,可以使用 @unittest.TestCase
类的装饰器方法(如 @unittest.skip
、@unittest.expectedFailure
)来标记测试方法,以实现跳过测试或标记预期失败。
import unittest
class MyTestCase(unittest.TestCase):
@unittest.skip("Skip this test for now")
def test_skip_this(self):
self.assertTrue(False)
@unittest.expectedFailure
def test_expected_failure(self):
self.assertTrue(False)