如何构造没有逻辑的配置数据类?

2024-06-28 18:57:14 发布

您现在位置:Python中文网/ 问答频道 /正文

在我们的项目中,我们需要描述我们正在使用的硬件的属性。然后在程序中使用这些信息来决定程序应该如何执行

我正试图找到适合这项工作的最佳数据结构,我一直在想,在这种情况下,pythonic方法会是什么

  • 这些属性在运行时不会更改,也不应意外更改

  • 此外,某些硬件非常相似,因此使用继承机制仅指定两个硬件之间的差异,而不是重新键入所有属性可能是有意义的

  • 许多属性来自可能值的列表(枚举)

  • 添加新属性或重命名现有属性应该很容易。例如,如果另一个硬件属性与程序的执行相关,我们可以轻松添加一个新属性(在编码时)。如果现有属性的命名与新属性太相似,我们可能需要对其进行重命名,以便更清楚地了解它们之间的区别

  • 最后一个要求(我认为这是一个有问题的要求)是我们希望这些属性不依赖于任何逻辑(例如,它们应该是直接赋值)。以下是对最后一项要求的澄清:

    name = "Joe" #OK
    
    if gender == Gender.male: #not OK
       name = "Joe"
    else:
       name = "Jane"
    

最后一个限制的原因是,我们希望能够在不执行代码的情况下(例如,通过浏览代码)对值进行概述。虽然上面的示例可读性很强,但当调用来自导入模块的一系列函数以获取值时,它会很快变得复杂。我们希望避免需要运行代码来查看属性值

目前我们使用的是JSON文件格式,默认情况下不允许任何代码,只包含纯值。但这带来了其他问题,例如,没有对继承的集成支持、更困难的重构、对第三方模块的依赖(pydantic)

  • 我已经研究了dataclass,但这并没有限制赋值逻辑
  • 我已经检查了@property decorator,但这也没有限制赋值逻辑
  • 我已经检查了NamedTuple,但这会造成继承问题(并且仍然允许添加逻辑)
  • 我已经看到一些帖子使用了源代码意识和ast.parse,但这似乎有点骇人听闻

最接近我的是使用dataclass(如果汽车示例不太现实,我很抱歉):

from dataclasses import dataclass, field
from enum import Enum

class TransmissionType(Enum):
    MANUAL = "Manual"
    AUTOMATIC = "Automatic"
    
class BodyType(Enum):
    COUPE = "Coupe"
    WAGON = "Wagon"
    
@dataclass (frozen=True)
class Car:
    transmissionType: TransmissionType = field(init=False)
    bodyType: BodyType = field(init=False)
    numberOfDoors: int = field(init=False)
    consumptionPer100km: int = field(init=False)
    
@dataclass (frozen=True)
class FancyModel2019(Car):
    transmissionType = TransmissionType.MANUAL
    bodyType = BodyType.COUPE
    consumptionPer100km = 5
    if bodyType == BodyType.COUPE: #This should not be possible
        numberOfDoors = 3
    else:
        numberOfDoors = 5
    
@dataclass (frozen=True)
class FancyModel2020(FancyModel2019):
    consumptionPer100km = 4
    
myCar = FancyModel2020()
print(myCar.numberOfDoors)

然而,这仍然允许程序员添加逻辑,以计算属性的值(numberOfDoors在上面的示例中),而不是只进行纯赋值。我正在寻找一种在编码时阻止/防止这种情况发生的方法

有更适合这项工作的结构吗


Tags: 代码name程序falsefield属性硬件init