如何有效地设计包含相关成员变量的类?

时间:2015-08-09 13:50:40

标签: python oop

假设我想要一个名为Num的类,它包含一个数字,一半和它的正方形。

我应该可以修改三个变量中的任何一个,它将影响它的所有相关成员变量。我应该能够使用三个值中的任何一个来实例化该类。

设计这个课程的最佳方法是什么,以便可以轻松修改并确保我不会遗漏任何东西?

我应该存储所有三个号码还是只存储主号码?

例如,这就是我在python中使用我的类的方法:

num = Num(5)
print num.n, num.half, num.square

它应该打印5,2.5和25

这很简单,但我也想用它的一半初始化。

num = Num(half=2.5)
print num.n, num.half, num.square

它还应该打印5,2.5和25

如何让init函数知道它的一半?

我还想修改任何一个号码,它会改变所有相关号码! E.g:

num.square = 100
print num.n, num.half, num.square

它应该打印10,5和100

任何关于如何设计课程的建议都将受到赞赏。

3 个答案:

答案 0 :(得分:4)

您需要属性,设置或获取任何值。使用关键字参数可以实现__init__的不同行为:

class Num(object):
    def __init__(self, n=None, half=None, square=None):
        self._n = 0
        if n is not None:
            self.n = n
        if half is not None:
            self.half = half
        if square is not None:
            self.square = square

    @property
    def n(self):
        return self._n

    @n.setter
    def n(self, n):
        self._n = n

    @property
    def half(self):
        return self._n * 0.5

    @half.setter
    def half(self, n):
        self._n = n * 2

    @property
    def square(self):
        return self._n ** 2

    @square.setter
    def square(self, n):
        self._n = n ** 0.5

n = Num(square=100)
print n.half

编辑:现在没有lambdas,在初始化时没有给出值,给出一个很好的默认值,否则不会产生AttributeError

答案 1 :(得分:4)

与@Daniel相同的解决方案 - 扩展,lambda-less,Python 3.3:

class Num:
#class Num(object): for Python 2.
    def __init__(self, n = None, half = None, square = None):
        if n is not None:
            self.n = n
        elif half is not None:
            self.half = half
        elif square is not None:
            self.square = square
        else:
            self.n = 0

    @property
    def n(self):
        return self.__n
    @n.setter
    def n(self, n):
        self.__n = n
    @property
    def half(self):
        return self.n / 2.0
    @half.setter
    def half(self, n):
        self.n = n * 2
    @property
    def square(self):
        return self.n ** 2
    @square.setter
    def square(self, n):
        self.n = n ** .5

>>> five = Num(n=5)
>>> five.half, five.n, five.square, five._Num__n
(2.5, 5, 25, 5)
>>>

答案 2 :(得分:1)

对于其他方法,您可以在__setattr__中应用逻辑:

class Num(object):
    def __init__(self, n=None, half=None, square=None):
        if all(arg is None for arg in (n, half, square)):
            raise ValueError("Must supply at least one arg.")
        if n is not None:
            self.n = n
        elif half is not None:
            self.half = half
        elif square is not None:
            self.square = square

    def __setattr__(self, key, value):
        dct = self.__dict__
        if key == "n":
            dct[key] = value
            dct["half"] = value / 2.
            dct["square"] = value ** 2
        elif key == "half":
            dct[key] = value
            dct["n"] = value * 2
            dct["square"] = self.n ** 2
        elif key == "square":
            dct[key] = value
            dct["n"] = value ** .5
            dct["half"] = self.n / 2.
        else:
            dct[key] = value