我有一个在实例化时采用单个参数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)
我认为这是一个相当笨重的解决方案。
解决此问题的首选方法是什么?还有其他更优雅的解决方案吗?这真的是一个问题;我应该只使用第一个选项并最终获得更多代码行吗?
答案 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)