目录
- 1.@staticmethod
- 2.@classmethod
- 3、@classmethod 与@staticmethod比较
- 4. @property
- 5.@abstractmethod
- 6.@wraps
- 7.@lru_cache
- 8.@timeout
- 9.@retry
Python 中有很多好用的装饰器,以下是一些常用的装饰器:
@staticmethod:将一个方法转换为静态方法,可以在不创建类实例的情况下调用。@classmethod:将一个方法转换为类方法,可以在不创建类实例的情况下调用,并且可以访问类的属性和方法。@property:将一个方法转换为属性,可以像访问属性一样访问方法,而不需要使用括号调用。@abstractmethod:定义一个抽象方法,子类必须实现该方法才能被实例化。@wraps:将一个函数的元信息(如函数名、文档字符串、参数列表等)复制到另一个函数中,可以避免装饰器对函数元信息的影响。@lru_cache:使用 LRU 算法实现的缓存装饰器,可以缓存函数的计算结果,避免重复计算。@timeout:设置函数的最大执行时间,如果函数执行时间超过设定的时间,就会抛出TimeoutError异常。@retry:在函数执行失败时自动重试,可以设置重试次数、重试间隔等参数。@asyncio.coroutine:将一个函数转换为协程函数,可以使用yield from语法实现异步操作。@asyncio.run:运行一个协程函数,可以简化异步代码的编写。
这些装饰器都是 Python 中常用的装饰器,可以帮助我们简化代码、提高效率、增强程序的可读性和可维护性。
class MyClass:
@staticmethod
def my_static_method(x, y):
return x + y
# 不需要创建类实例,直接调用静态方法
result = MyClass.my_static_method(1, 2)
print(result) # 输出 3
2.@classmethod
3、@classmethod 与@staticmethod比较
classmethod 和 staticmethod 都是 Python 中的装饰器,用于定义类方法和静态方法。虽然它们都可以在类中定义方法,通过类名直接调用,而不需要创建类的实例,但是它们有一些不同之处。
不同点:
classmethod 的第一个参数是类本身,通常命名为 cls,而 staticmethod 没有特殊的参数。
classmethod 可以访问和修改类的属性和方法,而 staticmethod 只能访问类的属性和方法,不能修改它们。
classmethod 可以被子类继承和重写,而 staticmethod 不会被继承和重写。
以下是一个简单的示例代码,演示了如何使用 classmethod 和 staticmethod:
class MyClass:
class_variable = 0
def __init__(self, instance_variable):
self.instance_variable = instance_variable
@classmethod
def class_method(cls):
cls.class_variable += 1
print("Class variable:", cls.class_variable)
@staticmethod
def static_method():
print("Static method")
# 调用类方法
MyClass.class_method() # 输出 Class variable: 1
# 创建类实例
obj = MyClass(10)
# 调用静态方法
obj.static_method() # 输出 Static method
# 调用类方法
obj.class_method() # 输出 Class variable: 2
将一个方法转换为属性,可以像访问属性一样访问方法,而不需要使用括号调用。
class MyClass:
def __init__(self, x):
self._x = x
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
# 访问属性 x,实际上调用的是方法 x()
obj = MyClass(1)
print(obj.x) # 输出 1
# 修改属性 x,实际上调用的是方法 x(value)
obj.x = 2
print(obj.x) # 输出 2
5.@abstractmethod
abstractmethod 是 Python 中的一个装饰器,用于定义抽象方法。抽象方法是一种没有实现的方法,它只是一个接口,需要在子类中实现。抽象方法通常用于定义一个类的接口,而不是具体的实现。
使用 abstractmethod 装饰器可以让我们在抽象类中定义抽象方法,强制要求子类实现这些方法。如果子类没有实现抽象方法,那么在实例化子类时会抛出 TypeError 异常。
以下是一个简单的示例代码,演示了如何使用 abstractmethod 装饰器定义抽象方法:
6.@wraps
wraps 是 Python 中的一个装饰器,用于修饰其他装饰器,它可以帮助我们保留被修饰函数的元信息,例如函数名、文档字符串、参数列表等。如果我们不使用 wraps 装饰器,那么被修饰函数的元信息可能会丢失或被修改,导致代码可读性和可维护性下降。
使用 wraps 装饰器的主要用途是在编写装饰器时,保留被修饰函数的元信息。例如,如果我们编写一个装饰器,用于记录函数的执行时间,那么使用 wraps 装饰器可以保留被修饰函数的函数名、文档字符串、参数列表等信息,使得调试和维护代码更加方便。
以下是一个简单的示例代码,演示了如何使用 wraps 装饰器保留被修饰函数的元信息:
from functools import wraps
import time
def timer(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} took {end_time - start_time:.2f} seconds")
return result
return wrapper
@timer
def my_func():
"""This is a docstring"""
print("Hello, world!")
my_func()
print("Function name:", my_func.__name__)
print("Docstring:", my_func.__doc__)
# (env) [hanhandi@VM-33-162-centos ~/hanhan_PythonScripts/装饰器使用]$ python other.py
# Hello, world!
# my_func took 0.00 seconds
# Function name: my_func
# Docstring: This is a docstring
在上面的代码中,我们定义了一个名为 timer 的装饰器,用于记录函数的执行时间。我们使用 @wraps 装饰器修饰了内部的 wrapper 函数,保留了被修饰函数的元信息。然后,我们定义了一个名为 my_func 的函数,并使用 @timer 装饰器修饰它。最后,我们调用了 my_func() 函数,并输出了它的执行时间、函数名和文档字符串。
使用 wraps 装饰器可以让我们编写更加健壮和可维护的装饰器,同时也可以提高代码的可读性和可维护性。
这个之前有讲解过,不过之前用的是cachetools:
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
# 缓存函数的计算结果,避免重复计算
result = fibonacci(10)
print(result) # 输出 55
8.@timeout
timeout 是 Python 中的一个装饰器,用于设置函数的最大执行时间。如果函数在规定的时间内没有执行完毕,那么装饰器会抛出 TimeoutError 异常,中断函数的执行。
使用 timeout 装饰器的主要用途是在编写需要限制执行时间的函数时,保证函数不会一直执行下去,避免出现死循环或长时间阻塞的情况。例如,如果我们编写一个函数,用于从远程服务器下载文件,那么使用 timeout 装饰器可以设置最大下载时间,避免下载过程中出现网络故障或服务器故障导致程序一直阻塞。
以下是一个简单的示例代码,演示了如何使用 timeout 装饰器设置函数的最大执行时间:
在上面的代码中,我们定义了一个名为 timeout 的装饰器,用于设置函数的最大执行时间。我们首先定义了一个名为 TimeoutError 的异常类,用于在函数超时时抛出异常。然后,我们定义了一个名为 decorator 的装饰器函数,它接受一个函数作为参数,并返回一个新的函数 wrapper。在 wrapper 函数中,我们使用 signal 模块设置了一个定时器,当函数执行时间超过规定的时间时,会抛出 TimeoutError 异常。最后,我们使用 @timeout(5) 装饰器修饰了 my_func 函数,设置了最大执行时间为 5 秒。在调用 my_func() 函数时,如果函数执行时间超过 5 秒,会抛出 TimeoutError 异常。
9.@retry
retry 是 Python 中的一个装饰器,用于在函数执行失败时自动重试。如果函数执行失败,装饰器会等待一段时间后再次执行函数,直到函数执行成功或达到最大重试次数为止。
使用 retry 装饰器的主要用途是在编写需要重试的函数时,保证函数能够在失败后自动重试,避免出现因网络故障、服务器故障或其他原因导致函数执行失败的情况。例如,如果我们编写一个函数,用于从远程服务器下载文件,那么使用 retry 装饰器可以设置最大重试次数和重试间隔时间,避免下载过程中出现网络故障或服务器故障导致程序中断。
以下是一个简单的示例代码,演示了如何使用 retry 装饰器设置函数的重试次数和间隔时间:
import time
class RetryError(Exception):
pass
def retry(max_retries, wait_time):
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(max_retries):
try:
result = func(*args, **kwargs)
return result
except Exception as e:
print(f"Function failed: {e}")
if i < max_retries - 1:
print(f"Retrying in {wait_time} seconds...")
time.sleep(wait_time)
raise RetryError(f"Function failed after {max_retries} retries")
return wrapper
return decorator
@retry(max_retries=3, wait_time=2)
def my_func():
import random
if random.random() < 0.8:
raise Exception("Random error")
else:
print("Function succeeded")
try:
my_func()
except RetryError as e:
print("Function failed:", e)
# Function failed: Random error
# Retrying in 2 seconds...
# Function failed: Random error
# Retrying in 2 seconds...
# Function failed: Random error
# Function failed: Function failed after 3 retries
在上面的代码中,我们定义了一个名为 retry 的装饰器,用于设置函数的最大重试次数和重试间隔时间。我们首先定义了一个名为 RetryError 的异常类,用于在函数重试次数达到最大值时抛出异常。然后,我们定义了一个名为 decorator 的装饰器函数,它接受一个函数作为参数,并返回一个新的函数 wrapper。在 wrapper 函数中,我们使用 for 循环和 try/except 语句实现了函数的重试逻辑。如果函数执行失败,会等待一段时间后再次执行函数,直到函数执行成功或达到最大重试次数为止。最后,我们使用 @retry(max_retries=3, wait_time=2) 装饰器修饰了 my_func 函数,设置了最大重试次数为 3 次,重试间隔时间为 2 秒。在调用 my_func() 函数时,如果函数执行失败,会自动重试,直到函数执行成功或达到最大重试次数为止。
使用 retry 装饰器可以让我们编写更加健壮和可靠的函数,避免出现因网络故障、服务器故障或其他原因导致函数执行失败的情况。同时,它也可以提高代码的可读性和可维护性。
class MyClass:
@staticmethod
def my_static_method(x, y):
return x + y
# 不需要创建类实例,直接调用静态方法
result = MyClass.my_static_method(1, 2)
print(result) # 输出 3
@classmethod3、@classmethod 与@staticmethod比较
classmethod 和 staticmethod 都是 Python 中的装饰器,用于定义类方法和静态方法。虽然它们都可以在类中定义方法,通过类名直接调用,而不需要创建类的实例,但是它们有一些不同之处。
不同点:
classmethod的第一个参数是类本身,通常命名为cls,而staticmethod没有特殊的参数。classmethod可以访问和修改类的属性和方法,而staticmethod只能访问类的属性和方法,不能修改它们。classmethod可以被子类继承和重写,而staticmethod不会被继承和重写。
以下是一个简单的示例代码,演示了如何使用 classmethod 和 staticmethod:
class MyClass:
class_variable = 0
def __init__(self, instance_variable):
self.instance_variable = instance_variable
@classmethod
def class_method(cls):
cls.class_variable += 1
print("Class variable:", cls.class_variable)
@staticmethod
def static_method():
print("Static method")
# 调用类方法
MyClass.class_method() # 输出 Class variable: 1
# 创建类实例
obj = MyClass(10)
# 调用静态方法
obj.static_method() # 输出 Static method
# 调用类方法
obj.class_method() # 输出 Class variable: 2
将一个方法转换为属性,可以像访问属性一样访问方法,而不需要使用括号调用。
class MyClass:
def __init__(self, x):
self._x = x
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
# 访问属性 x,实际上调用的是方法 x()
obj = MyClass(1)
print(obj.x) # 输出 1
# 修改属性 x,实际上调用的是方法 x(value)
obj.x = 2
print(obj.x) # 输出 2
5.@abstractmethod
abstractmethod 是 Python 中的一个装饰器,用于定义抽象方法。抽象方法是一种没有实现的方法,它只是一个接口,需要在子类中实现。抽象方法通常用于定义一个类的接口,而不是具体的实现。
使用 abstractmethod 装饰器可以让我们在抽象类中定义抽象方法,强制要求子类实现这些方法。如果子类没有实现抽象方法,那么在实例化子类时会抛出 TypeError 异常。
以下是一个简单的示例代码,演示了如何使用 abstractmethod 装饰器定义抽象方法:
6.
@wraps
wraps是 Python 中的一个装饰器,用于修饰其他装饰器,它可以帮助我们保留被修饰函数的元信息,例如函数名、文档字符串、参数列表等。如果我们不使用wraps装饰器,那么被修饰函数的元信息可能会丢失或被修改,导致代码可读性和可维护性下降。使用
wraps装饰器的主要用途是在编写装饰器时,保留被修饰函数的元信息。例如,如果我们编写一个装饰器,用于记录函数的执行时间,那么使用wraps装饰器可以保留被修饰函数的函数名、文档字符串、参数列表等信息,使得调试和维护代码更加方便。以下是一个简单的示例代码,演示了如何使用
wraps装饰器保留被修饰函数的元信息:from functools import wraps import time def timer(func): @wraps(func) def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f"{func.__name__} took {end_time - start_time:.2f} seconds") return result return wrapper @timer def my_func(): """This is a docstring""" print("Hello, world!") my_func() print("Function name:", my_func.__name__) print("Docstring:", my_func.__doc__) # (env) [hanhandi@VM-33-162-centos ~/hanhan_PythonScripts/装饰器使用]$ python other.py # Hello, world! # my_func took 0.00 seconds # Function name: my_func # Docstring: This is a docstring在上面的代码中,我们定义了一个名为
timer的装饰器,用于记录函数的执行时间。我们使用@wraps装饰器修饰了内部的wrapper函数,保留了被修饰函数的元信息。然后,我们定义了一个名为my_func的函数,并使用@timer装饰器修饰它。最后,我们调用了my_func()函数,并输出了它的执行时间、函数名和文档字符串。使用
wraps装饰器可以让我们编写更加健壮和可维护的装饰器,同时也可以提高代码的可读性和可维护性。这个之前有讲解过,不过之前用的是cachetools:
from functools import lru_cache @lru_cache(maxsize=128) def fibonacci(n): if n < 2: return n return fibonacci(n-1) + fibonacci(n-2) # 缓存函数的计算结果,避免重复计算 result = fibonacci(10) print(result) # 输出 558.
@timeout
timeout是 Python 中的一个装饰器,用于设置函数的最大执行时间。如果函数在规定的时间内没有执行完毕,那么装饰器会抛出TimeoutError异常,中断函数的执行。使用
timeout装饰器的主要用途是在编写需要限制执行时间的函数时,保证函数不会一直执行下去,避免出现死循环或长时间阻塞的情况。例如,如果我们编写一个函数,用于从远程服务器下载文件,那么使用timeout装饰器可以设置最大下载时间,避免下载过程中出现网络故障或服务器故障导致程序一直阻塞。以下是一个简单的示例代码,演示了如何使用
timeout装饰器设置函数的最大执行时间:在上面的代码中,我们定义了一个名为
timeout的装饰器,用于设置函数的最大执行时间。我们首先定义了一个名为TimeoutError的异常类,用于在函数超时时抛出异常。然后,我们定义了一个名为decorator的装饰器函数,它接受一个函数作为参数,并返回一个新的函数wrapper。在wrapper函数中,我们使用signal模块设置了一个定时器,当函数执行时间超过规定的时间时,会抛出TimeoutError异常。最后,我们使用@timeout(5)装饰器修饰了my_func函数,设置了最大执行时间为 5 秒。在调用my_func()函数时,如果函数执行时间超过 5 秒,会抛出TimeoutError异常。9.
@retry
retry是 Python 中的一个装饰器,用于在函数执行失败时自动重试。如果函数执行失败,装饰器会等待一段时间后再次执行函数,直到函数执行成功或达到最大重试次数为止。使用
retry装饰器的主要用途是在编写需要重试的函数时,保证函数能够在失败后自动重试,避免出现因网络故障、服务器故障或其他原因导致函数执行失败的情况。例如,如果我们编写一个函数,用于从远程服务器下载文件,那么使用retry装饰器可以设置最大重试次数和重试间隔时间,避免下载过程中出现网络故障或服务器故障导致程序中断。以下是一个简单的示例代码,演示了如何使用
retry装饰器设置函数的重试次数和间隔时间:import time class RetryError(Exception): pass def retry(max_retries, wait_time): def decorator(func): def wrapper(*args, **kwargs): for i in range(max_retries): try: result = func(*args, **kwargs) return result except Exception as e: print(f"Function failed: {e}") if i < max_retries - 1: print(f"Retrying in {wait_time} seconds...") time.sleep(wait_time) raise RetryError(f"Function failed after {max_retries} retries") return wrapper return decorator @retry(max_retries=3, wait_time=2) def my_func(): import random if random.random() < 0.8: raise Exception("Random error") else: print("Function succeeded") try: my_func() except RetryError as e: print("Function failed:", e) # Function failed: Random error # Retrying in 2 seconds... # Function failed: Random error # Retrying in 2 seconds... # Function failed: Random error # Function failed: Function failed after 3 retries在上面的代码中,我们定义了一个名为
retry的装饰器,用于设置函数的最大重试次数和重试间隔时间。我们首先定义了一个名为RetryError的异常类,用于在函数重试次数达到最大值时抛出异常。然后,我们定义了一个名为decorator的装饰器函数,它接受一个函数作为参数,并返回一个新的函数wrapper。在wrapper函数中,我们使用for循环和try/except语句实现了函数的重试逻辑。如果函数执行失败,会等待一段时间后再次执行函数,直到函数执行成功或达到最大重试次数为止。最后,我们使用@retry(max_retries=3, wait_time=2)装饰器修饰了my_func函数,设置了最大重试次数为 3 次,重试间隔时间为 2 秒。在调用my_func()函数时,如果函数执行失败,会自动重试,直到函数执行成功或达到最大重试次数为止。使用
retry装饰器可以让我们编写更加健壮和可靠的函数,避免出现因网络故障、服务器故障或其他原因导致函数执行失败的情况。同时,它也可以提高代码的可读性和可维护性。
No comments yet.