给定一个允许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
这是正确的方法吗?
答案 0 :(得分:2)
我认为你比这更复杂。如果变量是相关的,并且可以完全由另一个确定,则不需要存储三个变量。您可以存储一个变量,并动态计算其他变量。像:
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
或{{ 1}}代替)。
此外,不太优雅的是程序员可以实例化_z
。如您所见,这意味着它包含不一致。在这种情况下,也许值得提出错误。
您可以通过在init模块中添加以下检查来确保只提供一个参数:
Foo(x=1, y=425)
这里我们构造了一个所有非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.')
# ...
值的列表,如果有多个值,程序员提供了两个或多个值,那么最好提出异常。