10.装饰器
- 装饰器的基本用法
- 创建简单的装饰器
- 带参数的装饰器
- 装饰器链
- 类装饰器
- 内置装饰器
定义:装饰器是一个函数,它接受另一个函数作为参数,并返回一个新的函数。装饰器通常用于在函数执行前后添加额外的功能,如日志记录、权限检查、性能测试等。
1.基本用法
@decorator_function
def some_function():
pass
相当于:
def some_function():
pass
some_function = decorator_function(some_function)
2.创建简单的装饰器
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()
#输出:
#Something is happening before the function is called.
#Hello!
#Something is happening after the function is called.
说明:
- my_decorator是一个装饰器函数,它接受一个函数func作为参数。
- 在my_decorator内部,定义了一个嵌套函数wrapper,该函数在调用func之前和之后执行额外的打印操作。
- my_decorator返回wrapper函数。
3.带参数的装饰器
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before the function call.")
result = func(*args, **kwargs)
print("After the function call.")
return result
return wrapper
@my_decorator
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
#输出
#Before the function call.
#Hello, Alice!
#After the function call.
说明:
- wrapper函数使用*args和**kwargs来接收任意数量的位置参数和关键字参数。
- 在wrapper中,首先打印“Before the function call.”,然后调用原始函数func,并将参数传递给它。
- 函数执行完后,打印“After the function call.”,并返回原始函数的结果。
4.装饰器链
def decorator_one(func):
def wrapper():
print("Decorator One")
func()
return wrapper
def decorator_two(func):
def wrapper():
print("Decorator Two")
func()
return wrapper
@decorator_one
@decorator_two
def say_hello():
print("Hello!")
say_hello()
#输出:
#Decorator One
#Decorator Two
#Hello!
说明:
- say_hello函数被decorator_one和decorator_two装饰。
- 当调用say_hello时,首先执行decorator_one的wrapper,然后执行decorator_two的wrapper,最后执行say_hello。
5.类装饰器
def class_decorator(cls):
cls.extra_attribute = "Added by decorator"
return cls
@class_decorator
class MyClass:
pass
print(MyClass.extra_attribute) # 输出: Added by decorator
说明:
- class_decorator是一个类装饰器,它接受一个类cls作为参数。
- 在装饰器内部,向类添加一个新的属性extra_attribute。
- 使用@class_decorator装饰MyClass,使得MyClass在定义时就被修改。
6.内置装饰器
假设你有一个简单的装饰器,它在调用函数之前和之后打印一些信息,在这个例子中,my_decorator 是一个装饰器,它使用 functools.wraps(func) 来装饰 wrapper 函数。这样做的好处是,wrapper 函数将继承 func 的元数据。
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("Before calling the function")
result = func(*args, **kwargs)
print("After calling the function")
return result
return wrapper
@my_decorator
def say_hello(name):
"""Greet someone by their name."""
print(f"Hello, {name}!")
say_hello("Alice")
print(say_hello.__name__) # 输出: say_hello
print(say_hello.__doc__) # 输出: Greet someone by their name.
说明:在这个例子中,say_hello 函数被 my_decorator 装饰。由于使用了 functools.wraps,say_hello 的元数据(如 __name__ 和 __doc__)会被保留,如果没有使用 functools.wraps,say_hello.__name__ 会是 'wrapper',而 say_hello.__doc__ 会是 None,因为这些信息会被 wrapper 函数的元数据覆盖。