开放的编程资料库

当前位置:我爱分享网 > Python教程 > 正文

Python 数据类装饰器

Python数据类教程展示了如何在自定义类中使用Python中的数据类装饰器。数据类装饰器有助于减少一些样板代码。

Python数据类装饰器

dataclass装饰器用于自动生成类的特殊方法,包括__str____repr__。它有助于减少一些样板代码。dataclass装饰器位于dataclasses模块中。

dataclass装饰器检查类以查找字段。字段被定义为具有类型注释的类变量。

@dataclass
class Test:
...

@dataclass()
class Test:
...

@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
class Test:
...

这三个声明是等价的。如果没有在装饰器中设置参数,则使用默认参数。如果init参数设置为True,将生成__init__方法。如果类已经定义了__init__,则忽略该参数。如果repr参数设置为True,则__repr__将生成方法。如果该类已经定义了__repr__,则该参数将被忽略。如果eq参数设置为True,将生成__eq__方法。如果该类已经定义了__eq__,则忽略此参数。

如果order参数设置为True,则__lt____le____gt____ge__方法被生成。如果该类已经定义了任何方法,则引发ValueError。如果unsafe_hash定义为False,则__hash__方法根据eqfrozen的设置生成。如果frozen参数设置为True,则对字段的赋值将产生异常。

Python常规自定义类

在常规的自定义Python类中,我们手动提供构造函数和其他方法,例如__repr__

#!/usr/bin/python

class Person:

    def __init__(self, name, age):

        self.name = name
        self.age = age

    def __repr__(self):

        return f'Person{{name: {self.name}, age: {self.age}}}'


p = Person('John Doe', 34)
print(p)

该示例显示了一个带有构造函数和__repr__方法的Person类,它给出了对象的完整表示。

$ ./regular_class.py
Person{name: John Doe, age: 34}

Python数据类示例

以下示例显示了dataclass装饰器的简单用法。

#!/usr/bin/python

from dataclasses import dataclass

@dataclass
class Person:
    name: str
    age: int

p = Person('John Doe', 34)
print(p)

我们有一个包含两个字段的类:namestr

from dataclasses import dataclass

dataclass装饰器位于dataclasses模块中。

@dataclass
class Person:
    name: str
    age: int

我们在Person类上应用dataclass装饰器。

p = Person('John Doe', 34)
print(p)

创建了一个新的人物对象。它的__init__方法被调用,该方法由dataclass装饰器自动生成。

$ ./simple_dataclass.py
Person(name='John Doe', age=34)

Python数据类默认值

可以为字段提供默认值。

#!/usr/bin/python

from dataclasses import dataclass

@dataclass
class Person:
    name: str = 'unknown'
    age: int = 0

p = Person('John Doe', 34)
print(p)

p2 = Person()
print(p2)

在示例中,Person类有两个字段;这些字段有一些默认值。

@dataclass
class Person:
    name: str = 'unknown'
    age: int = 0

使用赋值运算符(=),我们为字段提供默认值。

p2 = Person()
print(p2)

当我们不在构造函数中提供值时,字段将具有默认值。

$ ./default_values.py
Person(name='John Doe', age=34)
Person(name='unknown', age=0)

数据类冻结参数

如果frozen参数设置为True,我们就不能给字段赋值。

#!/usr/bin/python

from dataclasses import dataclass

@dataclass(frozen=True)
class Person:
    name: str
    age: int

p = Person('John Doe', 34)
p.occupation = 'gardener'

print(p)
print(p.occupation)

在示例中,frozen参数设置为True。该程序失败并显示以下错误消息:dataclasses.FrozenInstanceError:cannotassigntofield'occupation'

数据类asdict函数

asdict函数将数据类实例转换为其字段的adict。

#!/usr/bin/python

from dataclasses import dataclass, asdict

@dataclass
class Person:
    name: str
    occupation: str
    age: int

p = Person('John Doe', 'gardener', 34)
print(p)

print(asdict(p))

在示例中,我们借助asdict函数打印Person类的字段。

$ ./as_dict_fun.py
Person(name='John Doe', occupation='gardener', age=34)
{'name': 'John Doe', 'occupation': 'gardener', 'age': 34}

第一行是__repr__方法的输出,第二行是字段字典。

数据类字段函数

使用field函数,我们可以提供一些额外的每个字段信息。

#!/usr/bin/python

from dataclasses import dataclass, field

@dataclass
class Person:
    name: str
    age: int
    occupation: str = field(init=False, repr=False)

p = Person('John Doe', 34)
print(p)

p.occupation = "Gardener"
print(f'{p.name} is a {p.occupation}')

在示例中,我们有一个额外的occupation字段。

occupation: str = field(init=False, repr=False)

occupation字段不包含在__init____repr__方法中。

$ ./fields.py
Person(name='John Doe', age=34)
John Doe is a Gardener

具有模式匹配的Python数据类

下一个示例使用具有模式匹配语法的数据类。

#!/usr/bin/python

from dataclasses import dataclass


@dataclass
class Point:
    x: int
    y: int


def check(p):
    match p:
        case Point(x=0, y=0):
            print("Origin")
        case Point(x, y) if y == 0:
            print(f"on x axis")
        case Point(x, y) if x == 0:
            print(f"on y axis")
        case Point(x, y) if x > 0 and y > 0:
            print("Q I")
        case Point(x, y) if x < 0 and y > 0:
            print("Q II")
        case Point(x, y) if x < 0 and y < 0:
            print("Q III")
        case Point(x, y) if x > 0 and y < 0:
            print("Q IV")
        case _:
            print("Not a point")


points = [Point(3, 0), Point(0, 0), Point(-4, -5), Point(-4, 0), Point(0, 5),
          Point(4, 8), Point(-5, 3), Point(6, -4)]

for p in points:
    check(p)

我们有一个Point对象列表。使用match/case关键字,我们将每个点分配给原点、x和y轴,或四个象限之一。

case Point(x=0, y=0):
    print("Origin")

在这种情况下,我们匹配具有x=0和y=0坐标的点。

case Point(x, y) if x > 0 and y > 0:
    print("Q I")

使用守卫,我们检查该点是否位于第一象限。

$ ./points.py 
on x axis
Origin
Q III
on x axis
on y axis
Q I
Q II
Q IV

在本教程中,我们使用了Python数据类装饰器。

列出所有Python教程。

未经允许不得转载:我爱分享网 » Python 数据类装饰器

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏