Python 如何使用装饰器(decorators)
1. 装饰器的基本概念
装饰器是一个函数,它接受一个函数作为参数,并返回一个新的函数。装饰器可以用于在函数调用前后添加额外的功能,或者修改函数的行为。
装饰器通常通过在函数定义前使用@decorator_name
语法来应用。
def 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
@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.
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
接受一个函数func
作为参数,并返回一个包装函数wrapper
。在包装函数中,首先打印一条消息,然后调用传入的函数,最后再打印一条消息。
使用装饰器
可以使用@my_decorator
语法来应用这个装饰器:
@my_decorator
def say_hello():
print("Hello!")
say_hello()
这等价于:
def say_hello():
print("Hello!")
say_hello = my_decorator(say_hello)
say_hello()
3. 装饰器的嵌套
可以将多个装饰器应用于同一个函数,这称为装饰器的嵌套。装饰器的应用顺序是自下而上的,即最内层的装饰器最先应用。
def decorator1(func):
def wrapper():
print("Decorator 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("Decorator 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
say_hello()
输出结果:
Decorator 1
Decorator 2
Hello!
4. 带参数的装饰器
装饰器本身也可以接受参数。为了实现这一点,我们需要再嵌套一层函数。
创建带参数的装饰器
def repeat(num):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num):
func(*args, **kwargs)
return wrapper
return decorator
使用带参数的装饰器
可以传递参数来控制装饰器的行为:
@repeat(3)
def say_hello():
print("Hello!")
say_hello()
输出结果:
Hello!
Hello!
Hello!
5. 类装饰器
除了函数装饰器,Python还支持类装饰器。类装饰器是一个实现了__call__
方法的类,这样的类可以像函数一样调用。
创建类装饰器
class MyDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("Something is happening before the function is called.")
self.func(*args, **kwargs)
print("Something is happening after the function is called.")
使用类装饰器
@MyDecorator
def say_hello():
print("Hello!")
say_hello()
输出结果:
Something is happening before the function is called.
Hello!
Something is happening after the function is called.
6. 内置装饰器
Python提供了一些内置的装饰器,如@staticmethod
、@classmethod
和@property
。这些装饰器常用于类的方法定义。
@staticmethod
@staticmethod
用于定义静态方法,静态方法不需要访问类或实例的属性和方法。
class MyClass:
@staticmethod
def static_method():
print("This is a static method.")
MyClass.static_method()
@classmethod
@classmethod
用于定义类方法,类方法的第一个参数是类本身(通常命名为cls
)。
class MyClass:
@classmethod
def class_method(cls):
print(f"This is a class method of {cls}.")
MyClass.class_method()
@property
@property
用于将方法转换为属性,以便通过属性访问方法的结果。
class MyClass:
def __init__(self, value):
self._value = value
@property
def value(self):
return self._value
@value.setter
def value(self, value):
self._value = value
obj = MyClass(42)
print(obj.value) # 输出: 42
obj.value = 99
print(obj.value) # 输出: 99
7. 装饰器的实际应用场景
装饰器在实际编程中有很多应用场景,下面我们列举一些常见的例子。
日志记录
装饰器可以用于记录函数的调用情况。
def log(func):
def wrapper(*args, **kwargs):
print(f"Calling function {func.__name__}")
result = func(*args, **kwargs)
print(f"Function {func.__name__} finished")
return result
return wrapper
@log
def say_hello():
print("Hello!")
say_hello()
输出结果:
Calling function say_hello
Hello!
Function say_hello finished
权限检查
装饰器可以用于检查用户是否有权限执行某个操作。
def requires_permission(permission):
def decorator(func):
def wrapper(user, *args, **kwargs):
if user.has_permission(permission):
return func(user, *args, **kwargs)
else:
print(f"User {user.name} does not have {permission} permission.")
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
@requires_permission("admin")
def delete_user(user):
print(f"User {user.name} deleted.")
admin_user = User("Admin", ["admin"])
normal_user = User("User", [])
delete_user(admin_user) # 输出: User Admin deleted.
delete_user(normal_user) # 输出: User User does not have admin permission.
缓存
装饰器可以用于缓存函数的返回结果,以提高性能。
def cache(func):
memo = {}
def wrapper(*args):
if args in memo:
return memo[args]
result = func(*args)
memo[args] = result
return result
return wrapper
@cache
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(30)) # 输出: 832040
计时
装饰器可以用于测量函数的执行时间。
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time:.4f} seconds")
return result
return wrapper
@timer
def long_running_function():
time.sleep(2)
long_running_function() # 输出: Function long_running_function took 2.0001 seconds
参数校验
装饰器可以用于验证函数参数的有效性。
def validate_args(func):
def wrapper(*args, **kwargs):
if any(arg < 0 for arg in args):
raise ValueError("Arguments must be non-negative")
return func(*args, **kwargs)
return wrapper
@validate_args
def add(a, b):
return a + b
print(add(3, 5)) # 输出: 8
# print(add(-1, 5)) # 抛出异常: ValueError: Arguments must be non-negative
原文地址:https://blog.csdn.net/Itmastergo/article/details/140461995
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!