如何修复Python Dataclass中继承子类的顺序

问题描述 投票:0回答:1

我正在尝试使用继承的纬度和经度子类为纬度和经度创建一个数据类。但是继承的子类的顺序是不正确的。

from dataclasses import dataclass


# Custom TypeValidator https://gist.github.com/rnag/db6bf83d9ca19dfe897d6ccabd4e2570
from validators import TypeValidator

@dataclass
class Latitude:
    lat: float | int = TypeValidator()

    def __post_init__(self):
        if not -90 <= self.lat <= 90:
            raise ValueError('Lat must be from -90 to 90')


@dataclass
class Longitude:
    lon: float | int = TypeValidator()

    def __post_init__(self):
        if not -180 <= self.lon <= 180:
            raise ValueError('Lon must be from -180 to 180')

@dataclass
class LatLonPoint(Latitude,Longitude):
    lat = Latitude()
    lon = Longitude()

但它把 lon 放在第一位:

print(LatLonPoint(1,1))

LatLonPoint(lon=1, lat=1)

像这样创建它的一个原因是我试图通过创建纬度和经度的子类来修复初始化后验证。我认为这意味着每次更新值时都会重新初始化子类。但这引入了这个排序问题。我读了一些有关 MRO 的文章。但是有没有办法在不引入 kw_only=True 的情况下修复顺序?

python inheritance multiple-inheritance python-dataclasses
1个回答
0
投票

你们都采取了错误的方法并且混淆了概念。

出于任何实际目的,您实际上不太可能需要纬度和经度的专门子类(尽管,是的,它们可能有一些用处)。

第二:这不是面向对象子类化的工作原理:您的类要么是IS,它们的超类是什么 - 在这种情况下,这意味着您的

LatLonPoint
应该同时“是”
Latitude
Longitude
坐标。或者,它可以拥有关系中的其他类 - 那么你的
LatLonPoint
拥有纬度和经度。

这才是你应该追求的目标。

还有一件没有意义的事情:您希望纬度成为一个值,而不是拥有“.lat”值。所以,如果你真的想要它,你可以创建继承自 float 的类 - 并且它们会忘记

dataclasses
:它们是一种在很多用例中抑制样板文件的机制 - 但并不意味着当一个用例想要专修一门课。

如果没有单独的纬度和经度类,您可以将

LatLongPoint
上的纬度和经度属性作为 properties - 这将是在 Python 中处理此问题的更短且直接的方法。这些作为数据类是可行的,但其他工具(例如类型检查器)可能会抱怨,因为这些字段不会包含适当的 float 实例作为默认值。

继承

float
有一些特殊性,通常被认为是更高级的主题 - 但它会更接近你正在做的事情。

并且,只是为了确保理解:像您所做的那样继承纬度和经度是没有意义的。

[WIP:代码示例]


© www.soinside.com 2019 - 2024. All rights reserved.