一个属性全部可选的类
我创建了一个类,里面的属性都是可选的。目前,我的代码中到处都是 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 个回答
它们真的不需要存在吗,还是说应该有一个默认值呢?无论哪种情况,看起来你已经学到了更好的方法——让同一个类的所有实例都有相同的属性是更好的选择。
使用 None
是处理未初始化名称的标准方法,但如果 None
可能作为一个有效值出现,你可以自己定义一个:
class UnInit(object):
"""
No value yet given to this attribute
"""
class Coordinate(object):
x = UnInit
y = UnInit
z = UnInit