__init __()的“私有”参数?

时间:2013-01-06 11:01:07

标签: python

我有一个在实例化时采用单个参数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)

但是,我不希望用户传递所有参数的值,a除外_b_c_d是实现细节。我可以简单地在docstring中声明不要传递多个参数。使用下划线在“私有”属性之前是为了反映这一点。

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

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)

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

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

2 个答案:

答案 0 :(得分:7)

_下划线约定通过python世界清晰而普遍。

您记录了您的“公开”属性,只使用带有下划线的默认参数到您的__init__方法。把事情简单化。

如果某人希望通过使用这些私有参数搞砸一个类,那么你不会阻止它们,而不是Python。

答案 1 :(得分: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)