python - 在 Python 数据类中使用描述符作为字段的正确方法是什么?

标签 python python-dataclasses python-descriptors

我一直在研究 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/

相关文章:

python - 如何使用 python 中的分页从 API 创建有效的 json 文件?

python - 使用谷歌应用引擎将文件插入谷歌驱动器。使用的python客户端api

python - 为什么在类上设置描述符会覆盖描述符?

python - 如何使用 Pandas 对每个页面每月的日期进行分组和计数?

python - Tensorflow:在时间流中的索引处查找张量

python - 在数据类表示中传递参数

python - 具有默认选项的数据类参数选择

python - 一起使用数据类和属性时出现奇怪的问题

python - __slot__ 描述符如何在 python 中工作?

Python 描述符