有没有办法检查默认值是否显式传递给数据类的实例?

Is there a way to check if the default values were explicitly passed in to an instance of a dataclass`

考虑以下 python 代码:

from dataclasses import dataclass

@dataclass
class Registration:
  category: str = 'new'

@dataclass
class Car:
  make: str = None
  category: str = None
  reg: Registration = None
 
  def __post_init__(self):
    ''' fill in any missing fields from the registration of car '''
    if self.reg:
      for var in vars(self.reg):
        if not self.var:
          self.var = self.reg.var


r = Registration()
a = Car(make='ford', category='used', reg=r)
# its unknown if b is used/new, so we explicitly pass it None
b = Car(make='ford', category=None, reg=r)

在上面的例子中,__post_init__ 应该填充 Car class 中的字段,如果它在创建 Car 对象期间没有被传入。但是,如果 None 作为字段值显式传入(在本例中为 category),则不应从 Registration 对象中覆盖它。但是上面的代码确实如此。我如何检测在对象创建期间显式传递的值与默认值?

如果有办法区分 None 显式传递 vs 对象通过 它的默认值。在像你这样的情况下,一种技术是使用 一种作为默认值的哨兵值。

@dataclass
class Car:
    NO_ARG = object()

    make: str = None
    category: str = NO_ARG
    reg: Registration = None

    def __post_init__(self):
        if self.reg:
            for var in vars(self.reg):
                if getattr(self, var) is self.NO_ARG:
                    setattr(self, var, getattr(self.reg, var))

但是,你也可能会把你自己发现的尴尬处境 作为一个信号,也许有更好的方法来模拟你的 对象。在不了解更多情况下 更广泛的背景很难提供明确的建议,但是 我会说你目前的策略让我觉得可疑,所以我 会鼓励您多考虑一下您的 OO 计划。

举一个替代模型的例子,而不是使用注册来 覆盖汽车的属性,您可以改为构建 属性 在 Car 属性时公开 Registration 属性 不见了。 class 的用户可以决定他们是否想要 该类别严格来自汽车,或者他们很乐意接受 来自注册的回退值(如果可用)。这种方法 也有权衡。

@dataclass
class Car:

    make: str = None
    category: str = None
    reg: Registration = None

    @property
    def category_reg(self):
        if self.category is None and self.reg:
            return self.reg.category
        else:
            return self.category