DataClass 是否适合替代字典?

Is DataClass a good fit to replace a dictionary?

我在代码中经常使用字典作为数据结构。而不是像 Python 那样返回多个值 Tuple 允许它:

def do_smth():
  [...]
  return val1, val2, val3

我更喜欢使用具有命名键的优点的字典。 但是对于复杂的嵌套字典,很难在其中导航。几年前当我用 JS 编码时,我也喜欢字典,因为我可以调用像 thing.stuff.foo 这样的子部分,而 IDE 帮助我构建了结构。

我刚刚在 python 中发现了新的 DataClass,除了替换字典外,我不确定这是什么原因?对于我所读到的内容,DataClass 内部不能有函数,并且简化了其参数的初始化。

我想对此发表评论,你如何使用 DataClass,或关于 python 中的字典。

我的看法。

A DataClass 不一定要替换字典。相反,它被用作一个对象来保存一些在应用程序建模中有意义的数据。

假设我们正在构建一个简单的地址簿。假设它只是存储一些数据,Person class 可以是一个数据 class,其中包含 namephone_number 等字段。然后我们可以使用字典来创建 namePerson 的查找,以便我们可以按名称检索此数据 class。

from dataclasses import dataclass
@dataclass
class Person:
    def __init__(self, name, address, phone_number):
        self.name = name
        self.address = address
        self.phone_number = phone_number

然后在应用的其他地方:

persons = <LIST OF PERSONS>
address_book = {person.name: person for person in persons}

这是一个基本的例子,但我希望它能理解这个想法。

当然有人会争论为什么在 namedtuple 就足够的情况下使用 dataclass

其他人也写过关于该主题的文章:

去吧,纯 OO 是否可以拥有纯数据 classes 尤其是在处理多线程时。不过,我的建议是尝试仅在需要和使用的地方插入此信息(将数据 class 与功能混合)。

Data类 更像是 NamedTuples 的替代品,然后是字典。

虽然 NamedTuples 被设计为不可变的,但 data类 可以通过在装饰器中设置 frozen=True 来提供该功能,但总体上提供了更大的灵活性。

如果您在 Python 代码中使用 type hints,它们就会发挥作用。

另一个优点如您所说 - 复杂的嵌套字典。您可以将 Data类 定义为您的类型,并以清晰简洁的方式在 Data类 中表示它们。

考虑以下因素:

@dataclass
class City:
    code: str
    population: int


@dataclass
class Country:
   code: str
   currency: str
   cities: List[City]


@dataclass
class Locations:
   countries: List[Country]

然后您可以编写函数,在其中用数据类名称作为类型提示注释函数参数并访问它的属性(类似于传入字典并访问它的键),或者构造数据类并输出它,即

def get_locations(....) -> Locations:
....

它使代码非常可读,而不是一个大而复杂的字典。

您还可以设置默认值,这在 NamedTuples 中是不允许的,但在字典中是允许的。

@dataclass
class Stock:
   quantity: int = 0

您还可以在装饰器中控制是否要对数据类进行排序等,就像是否要冻结它一样,而普通词典则不排序。 See here for more information

如果需要,您可以获得对象比较的所有好处,即 __eq__() 等。默认情况下,它们还带有 __init____repr__,因此您无需键入像正常 类.

一样手动退出这些方法

对字段的控制也大大增加,允许使用元数据等。

最后,您可以通过导入 from dataclasses import dataclass asdict

将其转换为字典