如何在 python 数据类中实现变量间依赖的封装
How to achieve encapsulation in python dataclasses with dependencies between variables
我最近了解到数据classes 在编写主要用作数据容器的 classes 时减少样板代码的好处。
我希望能够使用数据classes,但希望使用 private/protected 变量来保持我已经习惯的常规 classes 的封装级别and/or 个属性。
我希望能够封装两个字段,以便它们只根据某些预期规则一起更新。
举个最简单的例子:
class EncapsulatedClass:
def __init__(self, field1, field2):
validate_args(field1, field2)
self._field1 = field1
self._field2 = field2
def update_fields(self, arg1, arg2):
if arg1:
self._field1 += 1
if arg2:
self._field2 += 1
if arg1 and arg2:
self._field1 = 0
我喜欢这种行为的原因是它保证(直到用户修改受保护的参数)field1 和 field2 有一些预期的关系,这可以在初始化时验证,然后永远不需要再次验证。
但是,对于标准 class,我需要实施 __eq__
__repr__
和 __init__
,我宁愿避免减少样板文件。
有没有一种方法可以使用数据classes 和最少的样板来实现这种行为?
一般来说,不会。但具体取决于您要执行的操作,可能会有各种特定的解决方法。例如,在这里我可能会创建一个对元组进行操作的 属性。
class EncapsulatedClass:
def __init__(self, field1, field2):
self.field = (field1, field2)
@property
def field(self):
return (self._field1, self._field2)
@field.setter
def field(self, value):
v1, v2 = value # Here, just letting a possible exception propogate
if v1:
self._field1 += 1
if v2:
self._field2 += 1
if v1 and v2:
self._field1 = 0
# Now it's a wrapper around the setter
def update_fields(self, field1, field2):
self.field = (field1, field2)
您可以继续在数据类中使用 属性。可以定义 __post_init__
来初始化 属性,而不必重新实现将使用底层属性的所有内容。
@dataclass
class EncapsulatedClass:
_field1: int
_field2: int
def __post_init__(self):
self.field = (self._field1, self._field2)
@property
def field(self):
return (self._field1, self._field2)
@field.setter
def field(self, value):
v1, v2 = value # Here, just letting a possible exception propogate
if v1:
self._field1 += 1
if v2:
self._field2 += 1
if v1 and v2:
self._field1 = 0
def update_fields(self, field1, field2):
self.field = (field1, field2)
我最近了解到数据classes 在编写主要用作数据容器的 classes 时减少样板代码的好处。
我希望能够使用数据classes,但希望使用 private/protected 变量来保持我已经习惯的常规 classes 的封装级别and/or 个属性。
我希望能够封装两个字段,以便它们只根据某些预期规则一起更新。
举个最简单的例子:
class EncapsulatedClass:
def __init__(self, field1, field2):
validate_args(field1, field2)
self._field1 = field1
self._field2 = field2
def update_fields(self, arg1, arg2):
if arg1:
self._field1 += 1
if arg2:
self._field2 += 1
if arg1 and arg2:
self._field1 = 0
我喜欢这种行为的原因是它保证(直到用户修改受保护的参数)field1 和 field2 有一些预期的关系,这可以在初始化时验证,然后永远不需要再次验证。
但是,对于标准 class,我需要实施 __eq__
__repr__
和 __init__
,我宁愿避免减少样板文件。
有没有一种方法可以使用数据classes 和最少的样板来实现这种行为?
一般来说,不会。但具体取决于您要执行的操作,可能会有各种特定的解决方法。例如,在这里我可能会创建一个对元组进行操作的 属性。
class EncapsulatedClass:
def __init__(self, field1, field2):
self.field = (field1, field2)
@property
def field(self):
return (self._field1, self._field2)
@field.setter
def field(self, value):
v1, v2 = value # Here, just letting a possible exception propogate
if v1:
self._field1 += 1
if v2:
self._field2 += 1
if v1 and v2:
self._field1 = 0
# Now it's a wrapper around the setter
def update_fields(self, field1, field2):
self.field = (field1, field2)
您可以继续在数据类中使用 属性。可以定义 __post_init__
来初始化 属性,而不必重新实现将使用底层属性的所有内容。
@dataclass
class EncapsulatedClass:
_field1: int
_field2: int
def __post_init__(self):
self.field = (self._field1, self._field2)
@property
def field(self):
return (self._field1, self._field2)
@field.setter
def field(self, value):
v1, v2 = value # Here, just letting a possible exception propogate
if v1:
self._field1 += 1
if v2:
self._field2 += 1
if v1 and v2:
self._field1 = 0
def update_fields(self, field1, field2):
self.field = (field1, field2)