定义Python类实例属性

时间:2018-01-02 23:54:18

标签: python class properties getter-setter

给定一个允许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__负责处理。

现在我想做以下

  • 如果更改了3个变量中的任何一个,则其他变量会根据关系发生变化。

试图完成我的目标:

@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

这是正确的方法吗?

1 个答案:

答案 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.') # ...值的列表,如果有多个值,程序员提供了两个或多个值,那么最好提出异常。