5

我有一个在实例化时采用单个参数的类,该参数a存储在_a属性中。对于许多方法(运算符),我还需要_b在结果上设置一个属性。这目前以直接的方式实现:

class SomeClass(object):
    def __init__(self, a=0):
        self._a = a
        self._b = 0

    def __add__(self, other):
        result = self.__class__()
        result._b = self._a + other._a
        return result

现在,我有许多成员_b,例如_c_d,因此__add__每个属性都需要额外的一行。能够在对象实例化上传递这些将导致更简洁的代码:

class SomeClass(object):
    def __init__(self, a=0, _b=0):
        self._a = a
        self._b = 0

    def __add__(self, other):
        return self.__class__(_b=self._a + other._a)

但是,我不希望用户传递所有参数的值,除了aas _b_c并且_d是实现细节。我可以简单地在文档字符串中声明不要传递多个参数。在“私有”属性之前加上下划线旨在反映这一点。

或者,我可以尝试通过提供第二个私有构造函数来让用户更难行为不端:

class SomeClass(object):
    def __init__(self, a=0):
        self._a = a
        self._init()

    def _init(self, _b=0):
        self._b = _b

    @classmethod
    def _constructor(cls, a, _b):
        obj = cls(a)
        obj._init(b)
        return obj

    def __add__(self, other):
        return self.__class__._constructor(_b=self._a + other._a)

我认为这是一个相当笨拙的解决方案。

解决这个问题的首选方法是什么?还有其他更优雅的解决方案吗?这真的是个问题吗?我应该只使用第一个选项并最终得到更多代码行吗?

4

2 回答 2

7

下划线约定在_python 世界中是明确和普遍的。

您记录您的“公共”属性,并在您的__init__方法中使用带下划线的默认参数。把事情简单化。

如果有人通过使用这些私有参数来搞砸一个类,你不会阻止他们,而不是在 Python 中。

于 2013-01-06T11:04:14.360 回答
0

为了稍微整理一下,您可以_b在之前设置__init__

class SomeClass(object):
    _b = 0
    def __init__(self, a=0):
        self._a = a

    def __add__(self, other):
        result = self.__class__()
        result._b = self._a + other._a
        return result

或者如果有大量私有变量,将它们放入一个列表并做一些魔术?

class SomeClass(object):
    calculated_vars = ['_b'] # All your calculated variables

    def __init__(self, a=0):
        self._a = a

    def __getattr__(self, k):
        if k in self.calculated_vars:
            return 0 # Default value for calculated variables
        else:
            raise AttributeError('{} not found'.format(k))

    def __add__(self, other):
        result = self.__class__()
        result._b = self._a + other._a
        return result

if __name__ == '__main__':
    i = SomeClass(1)
    print '_a attr: ', i._a # 1
    print '_b attr: ', i._b # 0 (Default value)
    print '_c attr: ', i._c # AttributeError: _c not found

    i2 = SomeClass(3)
    i3 = i + i2
    print '_b attr: ', i3._b # 4 (Calculated value)
于 2013-01-06T11:12:53.693 回答