定义Python类实例属性

定义Python类实例属性,python,class,properties,getter-setter,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

给定允许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()
的实例时,用户需要提供其中一个实例,而
\uuuuu init\uuuuuu
会处理它

现在我想做以下几点

  • 如果三个变量中的任何一个发生变化,其他变量也会随之变化
为了实现这一目标,我做到了:

@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
因此,我们只在类上存储一个
\ux
属性,其余的所有getter和setter都使用
\ux
属性(我们当然可以使用
\uy
\uz

此外,程序员可以实例化一个
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.')

    # ...
类Foo(对象):
定义初始化(self,x=None,y=None,z=None):
数据=[i代表[x,y,z]中的i,如果i不是None]
如果len(数据)>1:
raise VALUERROR('提供了多个参数')
如果x不是无:
self.x=x
elif x不是无:
self.y=y
elif z不是无:
self.z=z
其他:
raise VALUERROR('提供x、y或z值')
#…

因此,这里我们构造了一个所有非
None
值的列表,如果有多个值,程序员提供两个或多个值,然后最好提出一个异常。

如果我提供
FooBar(x=1,y=1425)
?如果
x=2*y
,那么
self.\u y=value/2
x
的设置者。不是
值*2
。根据我的
\uuuuu init\uuuuu
x
优先,这就是原因,如果elif…。确定。我做的正好相反,你是对的。但我更担心的是实例变量的设置。为了避免“不一致”,在
if
子句上添加更多的条件很简单,例如:
如果x不是None,y是None,z是None:
。并对所有其他2种情况执行相同的操作,但这会变得疯狂(如果参数更多)。还有其他优雅的方法吗?好主意,是这样做的:
如果sum(i在局部变量中不是None().values())>2:raisevalueerror(“…”)
。非常感谢。