在python
中创建一个类,我们需要写__init__
方法进行初始化对象操作,需要对对象进一步说明的话,最好写一个__repr
方法,这样我们直接输出对象的话,方便理解这个对象是啥。但在python3.7以后的版本中给我们提供了一个更加简单的方式dataclasses
定义
首先我们用常规的方法创建一个类
class User: def __init__(self, name, age): self.name = name self.age = age def __repr__(self): return f"User-{self.name}" user = User("Tony", 18) print(user.name) # Tony print(user.age) # 18 print(user) # User-Tony
下面使用dataclasses
去创建一个类
from dataclasses import dataclass @dataclass class User: name: str age: int user = User("Tony", 18) print(user.name) # Tony print(user.age) # 18 print(user) # User(name="Tony", age=18)
可以看到相对于普通类的写法是不是显得简单很多
默认值
让我们看看如何给设置默认值
from dataclasses import dataclass @dataclass class User: name: str age: int = 18 user_1 = User("Tony") print(user_1.name) # Tony print(user_1.age) # 18 user_2 = User("Tom", 20) print(user_2.name) # Tom print(user_2.age) # 20
添加一个方法
from dataclasses import dataclass @dataclass class User: name: str age: int = 18 def age_difference(self, other): return self.age - other.age user_1 = User("tony", 20) user_2 = User("tom") user_1.age_difference(user_2) # 2
frozen
frozen
实例是在初始化对象后无法修改其属性的对象
@dataclass(frozen = True) class Number: val: int = 0
>>> a = Number(1) >>> a.val >>> 1 >>> a.val = 2 >>> Traceback (most recent call last): File “<stdin>”, line 1, in <module> File “<string>”, line 3, in __setattr__ dataclasses.FrozenInstanceError: cannot assign to field ‘val’
后期初始化处理
有了 dataclass
,需要定义一个 __init__
方法来将变量赋给 self
这种初始化操作已经得到了处理。但是我们失去了在变量被赋值之后立即需要的函数调用或处理的灵活性,我们可以通过__post_init__
来实现,例如以下在初始化之后立即计算整数和小数部分
import math @dataclass class FloatNumber: val: float = 0.0 def __post_init__(self): self.decimal, self.integer = math.modf(self.val)
>>> a = Number(2.2) >>> a.val >>> 2.2 >>> a.integer >>> 2.0 >>> a.decimal >>> 0.2
继承
Dataclasses
支持继承,就像普通的 Python 类一样
@dataclass class Person: age: int = 0 name: str @dataclass class Student(Person): grade: int
>>> s = Student(20, "John Doe", 12) >>> s.age >>> 20 >>> s.name >>> "John Doe" >>> s.grade >>> 12
Student
的参数是在类中定义的字段的顺序
field
先看下field
的原型
dataclasses.field(*, default=MISSING, default_factory=MISSING, repr=True, hash=None, init=True, compare=True, metadata=None)
通常我们无需直接使用,装饰器会根据我们给出的类型注解自动生成field,但有时候我们也需要定制这一过程,这时dataclasses.field
就显得格外有用了
from dataclasses import dataclass, field @dataclass class Position: lon: float = field(default=0.0, metadata={"unit": "degrees"}) lat: float = field(default=0.0, metadata={"unit": "degrees"})
>>>from dataclasses import fields >>>fields(Position)[1].metadata["unit"] >>>degrees
我们再来试下default_factory
,如果在创建对象时没有赋值,则使用该方法初始化该字段
from dataclasses import dataclass, field def get_grades(): return [random.randint(60, 100) for _ in range(3)] @dataclass class Student: grades: List[int] = field(default_factory=get_grades)
>>>Student().grades >>>[95, 89, 60]
当然我们也可以使用__post_init__
来实现
版权声明:如无特殊说明,文章均为本站原创,转载请注明出处
本文链接:https://www.ltfred.com/article/python-dataclass/