给定一个允许3种可能输入的类定义:
class FooBar(object):
def __init__(self, x=None, y=None, z=None):
if x is not None:
self.x = x
elif if y is not None:
self.y = y
elif if z is not None:
self.z = z
else:
raise ValueError('Please supply either x,y or z')
这3个输入相互关联,让我们说:
x = .5*y = .25*z
这也意味着:
y = .5*z = 2*x
和
z = 2*y = 4*x
在创建FooBar()
的实例时,用户需要提供其中一个,__init__
负责处理它。
现在我想做以下事情
为了实现这一点,我做了:
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
self._y = 2*self._x
self._z = 4*self._x
对其他人:
@property
def y(self):
return self._y
@y.setter
def y(self, value):
self._y = value
self._x = .5*self._y
self._z = 2*self._y
@property
def z(self):
return self._z
@z.setter
def z(self, value):
self._z = value
self._x = .25*self._z
self._y = .5*self._z
这是正确的方法吗?
我认为你让这比你更复杂。如果变量是相关的,并且可以完全由另一个确定,则不需要存储三个变量。您可以存储一个变量,并动态计算其他变量。喜欢:
class Foo(object):
def __init__(self, x=None, y=None, z=None):
if x is not None:
self.x = x
elif x is not None:
self.y = y
elif z is not None:
self.z = z
else:
raise ValueError('Provide an x, y, or z value.')
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = x
@property
def y(self):
return self._x / 2.0
@y.setter
def y(self, value):
self._x = 2 * value
@property
def z(self):
return self._x / 4.0
@z.setter
def z(self, value):
self._x = 4 * value
因此,我们只在类上存储_x
属性,并且所有其余的getter和setter都使用_x
属性(我们当然可以使用_y
或_z
)。
此外,一些不太优雅的东西是程序员可以实例化Foo(x=1, y=425)
。如您所见,这意味着它包含不一致。在这种情况下,也许值得提出错误。
您可以通过在init模块中添加以下检查来确保只提供一个参数:
class Foo(object):
def __init__(self, x=None, y=None, z=None):
data = [i for i in [x, y, z] if i is not None]
if len(data) > 1:
raise ValueError('Multiple parameters provided.')
if x is not None:
self.x = x
elif x is not None:
self.y = y
elif z is not None:
self.z = z
else:
raise ValueError('Provide an x, y, or z value.')
# ...
因此,我们构造了所有非None
值的列表,如果有多个值,程序员提供了两个或更多值,那么最好引发异常。