Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何构造没有逻辑的配置数据类?_Python_Python 3.x_Design Patterns_Architecture - Fatal编程技术网

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

Python 如何构造没有逻辑的配置数据类?,python,python-3.x,design-patterns,architecture,Python,Python 3.x,Design Patterns,Architecture,在我们的项目中,我们需要描述我们正在使用的硬件的属性。然后在程序中使用这些信息来决定程序应该如何执行 我正试图找到适合这项工作的最佳数据结构,我一直在想,在这种情况下,pythonic方法会是什么 这些属性在运行时不会更改,也不应意外更改 此外,某些硬件非常相似,因此使用继承机制仅指定两个硬件之间的差异,而不是重新键入所有属性可能是有意义的 许多属性来自可能值的列表(枚举) 添加新属性或重命名现有属性应该很容易。例如,如果另一个硬件属性与程序的执行相关,我们可以轻松添加一个新属性(在编码

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

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

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

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

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

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

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

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

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

  • 我已经研究了
    dataclass
    ,但这并没有限制赋值逻辑
  • 我已经检查了@property decorator,但这也没有限制赋值逻辑
  • 我已经选中了
    NamedTuple
    ,但这会造成继承问题(仍然允许添加逻辑)
  • 我见过一些帖子将源代码意识与
    ast.parse
    结合使用,但这似乎有点骇人听闻
最接近我的是使用dataclass(如果汽车示例不太现实,我很抱歉):

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


是否有更适合此工作的结构?

不清楚您所说的“这不限制分配逻辑”是什么意思。例如,您可以将数据类设置为
冻结=True
,因此对字段的赋值会引发异常。还不清楚“添加新属性或重命名现有属性应该很容易”是什么意思。。因为您还说过“这些属性在运行时不会更改”。我认为这里的示例比需求列表更有用。请给出一个预期使用的示例,以及您尝试使用DataClass或namedtuples的情况,以及失败的原因。@GinoMempin我已经添加了一个示例来说明我如何使用它。JSON实现(未显示,因为它非常复杂)解决了避免属性中任何逻辑的需求,而我刚才添加的示例满足其他需求,但它允许添加任意逻辑(代码)。检查示例中的注释,以查看哪个部分存在问题。我还添加了关于添加/重命名属性的说明。如果您认为任何进一步的澄清都会有用,请告诉我。不清楚您所说的“这不限制分配逻辑”是什么意思。例如,您可以将数据类设置为
冻结=True
,因此对字段的赋值会引发异常。还不清楚“添加新属性或重命名现有属性应该很容易”是什么意思。。因为您还说过“这些属性在运行时不会更改”。我认为这里的示例比需求列表更有用。请给出一个预期使用的示例,以及您尝试使用DataClass或namedtuples的情况,以及失败的原因。@GinoMempin我已经添加了一个示例来说明我如何使用它。JSON实现(未显示,因为它非常复杂)解决了避免属性中任何逻辑的需求,而我刚才添加的示例满足其他需求,但它允许添加任意逻辑(代码)。检查示例中的注释,以查看哪个部分存在问题。我还添加了关于添加/重命名属性的说明。如果您认为任何进一步的澄清都是有用的,请告诉我。
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)