Python 中的装饰器(Decorator)是一种高级特性,用于修改或扩展函数或方法的行为,而无需改变其代码。装饰器本质上是一个高阶函数,它接受一个函数作为参数,并返回一个新函数。
装饰器的基本语法
装饰器的基本语法是使用 @decorator_name
语法糖,将装饰器应用于函数或方法上。例如:
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
在这个例子中,my_decorator
是一个装饰器,它在 say_hello
函数前后添加了额外的行为。运行 say_hello()
的输出如下:
Something is happening before the function is called.
Hello!
Something is happening after the function is called.
装饰器的详细解释
-
定义装饰器:装饰器是一个函数,它接收另一个函数作为参数,通常在内部定义一个嵌套函数(
wrapper
),并返回这个嵌套函数。 -
应用装饰器:使用
@decorator_name
语法糖,可以将装饰器应用于函数。在函数定义前加上@my_decorator
,相当于say_hello = my_decorator(say_hello)
。 -
调用被装饰的函数:当调用被装饰的函数时,实际上调用的是装饰器返回的嵌套函数
wrapper
,其中包含了对原始函数func
的调用以及任何额外的逻辑。
带参数的装饰器
装饰器也可以处理带参数的函数。只需要确保 wrapper
函数接受合适的参数并传递给被装饰的函数。例如:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before function execution")
result = func(*args, **kwargs)
print("After function execution")
return result
return wrapper
@my_decorator
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
运行 greet("Alice")
的输出如下:
Before function execution
Hello, Alice!
After function execution
可参数化的装饰器
有时我们希望装饰器本身也接受参数,这时需要再嵌套一层函数:
def repeat(num_times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(num_times=3)
def say_hello():
print("Hello!")
say_hello()
运行 say_hello()
的输出如下:
Hello!
Hello!
Hello!
使用内置装饰器
Python 提供了一些内置装饰器,如 @staticmethod
、@classmethod
和 @property
。
class MyClass:
@staticmethod
def static_method():
print("This is a static method.")
@classmethod
def class_method(cls):
print("This is a class method.")
@property
def name(self):
return "MyClass"
# 调用静态方法和类方法
MyClass.static_method()
MyClass.class_method()
# 使用属性方法
obj = MyClass()
print(obj.name)
输出如下:
This is a static method.
This is a class method.
MyClass
总结
装饰器是一个强大的工具,可以用来修改或扩展函数或方法的行为,而无需更改其代码。它们常用于日志记录、访问控制、性能计数、缓存等场景。通过理解和熟练使用装饰器,可以大大提高代码的可读性和可复用性。