python-装饰器

装饰器

记录看别人源码过程中一些常遇到的装饰器。

@staticmethod :

@staticmethod 装饰器用于将一个方法声明为静态方法。静态方法是与类相关联的方法,但与类的实例无关,因此它们不需要访问类的实例变量或方法,也不需要访问实例本身。静态方法通常用于执行与类相关的操作,但不需要实例化类。

@staticmethod 装饰器的主要作用如下:

  1. 与类关联而不依赖于实例:静态方法属于类而不属于类的实例。这意味着你可以通过类名来调用静态方法,而无需创建类的实例。这使得它们可以在不需要类的实例的情况下执行某些操作。

  2. 避免访问实例变量:静态方法不会自动获取类的实例或类本身的引用,因此它们通常用于执行独立于类实例的操作。这意味着它们无法访问或修改实例变量,因为它们没有 self 参数。

  3. 类级别的操作:静态方法通常用于执行与整个类相关的操作,例如工具函数、实用程序方法或执行不依赖于实例状态的计算。

以下是一个示例,说明了如何使用 @staticmethod 装饰器来定义和使用静态方法:

1
2
3
4
5
6
7
class MathUtils:
@staticmethod
def add(x, y):
return x + y

result = MathUtils.add(10, 5) # 通过类名调用静态方法
print(result) # 输出 15

在这个示例中,add 方法是一个静态方法,它不需要类的实例,可以直接通过类名 MathUtils 来调用。静态方法在不需要访问实例状态的情况下执行一个简单的数学操作。

总之,@staticmethod 装饰器用于定义静态方法,这些方法与类相关联但与类的实例无关,可以在不创建类实例的情况下调用。它们通常用于执行与类相关的操作,但不需要访问实例变量或方法。

@property

@property 装饰器是 Python 中用于创建属性的一种方式,它可以让你定义一个方法,但可以像访问类的属性一样访问这个方法,而不需要显式地调用方法。这种方法的主要作用是将一个方法转化为只读属性,让外部代码可以更容易地访问和使用类的属性,同时隐藏内部实现的细节。

以下是 @property 装饰器的作用详解:

  1. 将方法转化为属性@property 装饰器可以应用于一个方法,使该方法可以像属性一样访问。这意味着你可以通过属性名来获取方法的返回值,而不需要在属性名后加括号调用方法

  2. 隐藏方法的调用:使用属性而不是方法调用可以使代码更清晰,因为它让属性的访问看起来更像变量的访问,而不是函数的调用。

  3. 允许属性访问和设置:你可以通过定义一个与属性同名的 setter 方法,使用 @property 装饰器的 @属性名.setter 子装饰器,从而允许属性的设置。这使得你可以在外部代码中像操作属性一样设置属性值。

  4. 实现计算属性:你可以在 @property 方法中编写复杂的逻辑,以根据类的状态计算属性的值。这样,你可以将属性视为类状态的派生值。

以下是一个示例,说明了如何使用 @property 装饰器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Circle:
def __init__(self, radius):
self._radius = radius

@property
def radius(self):
return self._radius

@property
def diameter(self):
return 2 * self._radius

@property
def area(self):
return 3.14159265359 * self._radius * self._radius

@radius.setter
def radius(self, value):
if value < 0:
raise ValueError("Radius cannot be negative")
self._radius = value

# 创建 Circle 实例
circle = Circle(5)

# 访问属性
print(circle.radius) # 输出 5
print(circle.diameter) # 输出 10
print(circle.area) # 输出 78.539816339745

# 设置属性
circle.radius = 7
print(circle.radius) # 输出 7

在这个示例中,Circle 类定义了三个只读属性 radiusdiameterarea,并定义了一个 setter 方法来设置 radius 属性。这使得用户可以轻松访问这些属性,同时确保 radius 的值始终为非负数。

@classmethod

在Python中,@classmethod 装饰器用于定义一个类方法(class method)。类方法是绑定到类而不是实例的方法,因此它可以在不创建类的实例的情况下被调用。通常,类方法用于执行与类本身相关的操作,而不是与实例相关的操作。

下面是 @classmethod 装饰器的详细解释:

  1. 定义类方法:
    使用 @classmethod 装饰器,可以将一个普通的方法转换为类方法。类方法的第一个参数通常命名为 cls,表示类本身。

    1
    2
    3
    4
    class MyClass:
    @classmethod
    def my_class_method(cls, arg1, arg2):
    # 类方法的实现
  2. 调用类方法:
    类方法可以通过类名直接调用,也可以通过类的实例调用。

    1
    2
    3
    MyClass.my_class_method(arg1, arg2)  # 通过类名调用类方法
    obj = MyClass()
    obj.my_class_method(arg1, arg2) # 通过类的实例调用类方法
  3. 类方法的特点:

    • 类方法是绑定到类的,因此它可以访问类级别的属性和方法。
    • 类方法不能访问实例级别的属性和方法,因为它没有对实例的引用。
    • 类方法通常用于工厂方法、创建实例、或执行与类相关的操作。

下面是一个简单的示例,演示如何使用 @classmethod 装饰器定义和调用类方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class MyClass:
class_variable = 0

def __init__(self, value):
self.value = value

@classmethod
def increment_class_variable(cls):
cls.class_variable += 1

def display(self):
print(f"Instance value: {self.value}")
print(f"Class variable: {self.class_variable}")

# 创建实例
obj1 = MyClass(10)
obj2 = MyClass(20)

# 调用类方法,增加类变量的值
MyClass.increment_class_variable()

# 显示实例属性和类属性
obj1.display()
obj2.display()

在上述示例中,@classmethod 装饰器用于定义 increment_class_variable 类方法,该方法可以增加类变量 class_variable 的值。类方法可以通过类名调用,也可以通过实例调用。

自定义的装饰器

@timer:测量执行时间

1
2
3
4
5
6
7
8
9
10
11
12
13
import time
def timer(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 to execute.")
return result
return wrapper

@timer
def my_data_processing_function():
# your code

@debuger:

1
2
3
4
5
6
7
8
9
10
def debug(func):
def wrapper(*args, **kwargs):
print(f"Debugging {func.__name__} - args: {args}, kwargs: {kwargs}")
return func(*args, **kwargs)

return wrapper

@debug
def complex_data_processing(arg1, arg2):
# Your complex data processing code here