我一直在研究 python 数据类并且想知道:制作一个或某些字段描述符的最优雅或最 pythonic 的方法是什么?
在下面的示例中,我定义了一个 Vector2D 类,它应该根据其长度进行比较。
from dataclasses import dataclass, field
from math import sqrt
@dataclass(order=True)
class Vector2D:
x: int = field(compare=False)
y: int = field(compare=False)
length: int = field(init=False)
def __post_init__(self):
type(self).length = property(lambda s: sqrt(s.x**2+s.y**2))
Vector2D(3,4) > Vector2D(4,1) # True
虽然此代码有效,但它会在每次创建实例时触及类,是否有更易读/更少hacky/更有意的方式来一起使用数据类和描述符?
只需将 length 作为属性而不是字段即可,但这意味着我必须编写 __lt__
, et.al.我自己。
我发现的另一个解决方案同样没有吸引力:
@dataclass(order=True)
class Vector2D:
x: int = field(compare=False)
y: int = field(compare=False)
length: int = field(init=False)
@property
def length(self):
return sqrt(self.x**2+self.y**2)
@length.setter
def length(self, value):
pass
引入一个无操作 setter 是必要的,因为显然数据类创建的 init 方法试图分配给 length 即使没有默认值并且它显式设置 init=False
...
肯定有更好的方法吧?
最佳答案
可能无法回答您的确切问题,但您提到您不想将 length 作为属性和 not 字段的原因是因为您必须这样做
write
__lt__
, et.al by myself
虽然您确实必须自己实现 __lt__
,但实际上您可以只实现那个
from functools import total_ordering
from dataclasses import dataclass, field
from math import sqrt
@total_ordering
@dataclass
class Vector2D:
x: int
y: int
@property
def length(self):
return sqrt(self.x ** 2 + self.y ** 2)
def __lt__(self, other):
if not isinstance(other, Vector2D):
return NotImplemented
return self.length < other.length
def __eq__(self, other):
if not isinstance(other, Vector2D):
return NotImplemented
return self.length == other.length
print(Vector2D(3, 4) > Vector2D(4, 1))
之所以可行,是因为 total_ordering
只是添加了所有其他基于 __eq__
和 __lt__
关于python - 在 Python 数据类中使用描述符作为字段的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68652100/