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__
方法根据eq
和frozen
的设置生成。如果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)
我们有一个包含两个字段的类:name
和str
。
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教程。