dataclass一些用法备忘

先给出一个程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import random
import string

def generate_id() -> str:
return ''.join(random.choices(string.ascii_uppercase, k=12))

class Person:
def __init__(self, name: str, address: str):
self.name = name
self.address = address

def __str__(self) -> str:
return f'{self.name} lives at {self.address}'

def main() -> None:
person = Person('John', '123 Main St')
print(person)

if __name__ == '__main__':
main()

输出:

1
John lives at 123 Main St

class Person比较繁杂,可以使用dataclass来直接定义这个类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import random
import string
from dataclasses import dataclass,field

def generate_id() -> str:
return ''.join(random.choices(string.ascii_uppercase, k=12))

@dataclass
class Person:
name: str
address: str

def main() -> None:
person = Person('John', '123 Main St')
print(person)

if __name__ == '__main__':
main()

其中,@dataclass 是 Python 3.7 引入的一个装饰器,用于简化创建包含数据的类(data classes)的过程。通过添加 @dataclass 装饰器,你可以自动为类生成一些常见的方法,比如构造方法、__repr____eq____ge__ 等。这样可以减少编写样板代码的工作量,提高代码的可读性和可维护性。可以根据需要为属性添加其他的装饰器,比如 @property@classmethod 等,以满足特定的需求。

可以设置默认值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@dataclass
class Person:
name: str
address: str
active: bool = True
email_addresses: list[str]=field(default_factory=list)
# 这里不能用list[str] = [],因为这样会导致所有实例共享同一个list
id: str = field(default_factory=generate_id, init=False)
# init=False表示这个字段不会被传入到__init__函数中,而是在__post_init__函数中被初始化(这个函数是dataclass自动生成的,不能手动设置)
_search_string: str = field(init=False, repr=True)
# repr=False表示这个字段不会被打印出来

def __post_init__(self) -> None:
self._search_string = f'{self.name} {self.address}'



# Person(name='John', address='123 Main St', active=True, email_addresses=[], id='BUUDWBCDMRMB', _search_string='John 123 Main St')

`

1
@dataclass(kw_only=True)

要求person = Person('John', '123 Main St')必须加上name=’John’

1
print(person.__dict__['name'])

只输出name,__dict__方法自动就有,结果和print(person.name)一样