一个属性全部可选的类

3 投票
1 回答
2350 浏览
提问于 2025-04-17 19:34

我创建了一个类,里面的属性都是可选的。目前,我的代码中到处都是 try: ... except AttributeError: ... 这样的块,但我在想,这样做是否是最好的方法。

现在我打算改用 None 类型来表示每个未知的属性,我觉得这样让我的代码看起来更好,但我还是在想是否有更好的方法,或者我是否只能接受可选属性带来的测试。

我正在尝试创建一个 Coordinates 类,它需要以特殊的方式进行修改,而这些值通常是事先不知道的,但需要通过其他实例来计算,因此这些值必须是可选的。

我很想听听大家的经验和建议。

编辑:

谢谢大家的回答!你们都很快... 而我比较慢,抱歉。由于这个话题比较抽象,我需要花更多时间思考一下。
我接受Ethan的回答作为解决方案,因为我觉得这是我接下来要研究的方向。我会发一些代码来澄清以下的说法。我的旧代码在 __add__ 方法中是这样的:

def __add__(self, other):
  """Add the given *masses* and calculate the resulting center of
  gravity. *other* must be a :meth:`putzmeister.Masse` instance or 0.
  """
  if other == 0:
    result = self.copy()
    result.label = None
    return result
  elif not isinstance(other, type(self)):
    raise TypeError('Error: second operand is not a Masse instance')
  mass = self.masse + other.masse
  result = type(self)(masse=mass)
  try:   result.x = (self.x*self.masse + other.x*other.masse)/mass
  except AttributeError: pass
  try:   result.y = (self.y*self.masse + other.y*other.masse)/mass
  except AttributeError: pass
  try:   result.z = (self.z*self.masse + other.z*other.masse)/mass
  except AttributeError: pass
  result._set_categories( self, other, action='add')
  return result

现在看起来是这样的:

def __add__(self, other):
  """Overwrite operator "+": add the given masses and calculate the resulting center of
  gravity.
  """
  if other == 0:
    result = self.copy()
    result.label = None
    return result
  elif not isinstance(other, type(self)):
    raise TypeError('Error: second operand is not a Masse instance')
  mass = self.masse + other.masse
  result = type(self)(masse=mass)
  for a in ('x','y','z'):
    c1 = getattr(self, a)
    c2 = getattr(other,a)
    if c1 is None or c2 is None: setattr(result, a, None)
    else: setattr(result, a, (c1*self.masse + c2*other.masse)/mass )
  result._set_categories( self, other, action='add')
  return result

使用 None 类型作为 <unset state> 是可以的。现在的问题是,0是所有坐标的有效值,所以我总是得检查 if attribute is not None,而不是 if attribute,我觉得后者会让代码看起来更简洁。

不过,我的理想是,在赋值 z = x + y 时,我的代码能够首先检查 z 是否存在且类型正确,如果是的话,就根据数学表达式设置 x 和 y 的值(例如对于 y:如果 z 有某些属性,而 x 也有相同的属性...)。如果 z 不存在,就创建它并设置所有可设置的值。我不太确定这样的事情是否能做到...

再次感谢大家的回答。

1 个回答

1

它们真的不需要存在吗,还是说应该有一个默认值呢?无论哪种情况,看起来你已经学到了更好的方法——让同一个类的所有实例都有相同的属性是更好的选择。

使用 None 是处理未初始化名称的标准方法,但如果 None 可能作为一个有效值出现,你可以自己定义一个:

class UnInit(object):
    """
    No value yet given to this attribute
    """

class Coordinate(object):
    x = UnInit
    y = UnInit
    z = UnInit

撰写回答