Python:显式调用超类的类方法可以工作,但由于超类中的可选变量,使用 super() 调用它会中断

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

我试图调用超类(示例)的类方法,但是当我这样做时,我收到类型错误。 我可以通过显式调用 Sample.from_dict(row) 而不是 super().from_dict(row) 来解决此问题。 我只是不明白其中的区别:

超类:

from typing import Optional
from exceptions import InvalidSampleError

class Sample:
    def __init__(
            self,
            sepal_length: float,
            sepal_width: float,
            petal_length: float,
            petal_width: float,
            species: Optional[str] = None,
            classification: Optional[str] = None,
    ) -> None:
        self.sepal_length = sepal_length
        self.sepal_width = sepal_width
        self.petal_length = petal_length
        self.petal_width = petal_width
        self.species: Optional[str] = species
        self.classification: Optional[str] = classification

    @classmethod
    def from_dict(cls, row: dict[str, str]) -> "Sample":
        try:
            return cls(
                sepal_length=float(row["sepal_length"]),
                sepal_width=float(row["sepal_width"]),
                petal_length=float(row["petal_length"]),
                petal_width=float(row["petal_width"]),
            )
        except ValueError as ex:
            raise InvalidSampleError(f"invalid {row!r}")

子类:

from sample import Sample
from typing import Optional

class InvalidSampleError(ValueError):
    """Source data file has invalid data representation"""

class Species(Enum):
    Setosa = "Iris-setosa"
    Versicolor = "Iris-versicolor"
    Viginica = "Iris-virginica"

class KnownSample(Sample):
    def __init__(
            self,
            sepal_length: float,
            sepal_width: float,
            petal_length: float,
            petal_width: float,
            species: str,
            classification: Optional[str] = None,
    ) -> None:
        super().__init__(sepal_length, sepal_width, petal_length, petal_width, species, classification)

    @classmethod
    def from_dict(cls, row: dict[str, str]) -> "KnownSample":
        # Validate the species
        if row["species"] not in [species.value for species in Species]:
            raise InvalidSampleError(f"invalid species in {row!r}")

        try:
            # Create a Sample instance with the species argument added
            sample = Sample.from_dict(row)

            # Now return a KnownSample using the additional 'species' argument
            return cls(
                sepal_length=sample.sepal_length,
                sepal_width=sample.sepal_width,
                petal_length=sample.petal_length,
                petal_width=sample.petal_width,
                species=row["species"],  # Pass the species from the row to the KnownSample
                classification=sample.classification
            )
        except ValueError as ex:
            raise InvalidSampleError(f"invalid {row!r}")

用途:

if __name__ == '__main__':
    ks = {"sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2, "species": "Iris-setosa"}
    us = {"sepal_length": 5.1, "sepal_width": 3.5, "petal_length": 1.4, "petal_width": 0.2}
    known_sample = KnownSample.from_dict(ks)
    unknown_sample = Sample.from_dict(us)
    print(known_sample)
    print(unknown_sample)

这可行,但是当我更换线路时:

sample = Sample.from_dict(row)
和:
sample = super().from_dict(row)
我明白了
TypeError: KnownSample.__init__() missing 1 required positional argument: 'species'

python super
1个回答
0
投票

super().from_dict(row)
并不意味着“打电话
Sample.from_dict(row)
”。它的意思是“找到下一个
from_dict
实现(恰好是
Sample
中的实现),但在
cls
上调用它”。

您不想构建任何

cls
恰好存在的实例。您想要构建
Sample
的实例。由于构造函数签名不匹配,
Sample
from_dict
实现无论如何都无法正确处理
KnownSample
。所以你应该打电话给
Sample.from_dict(row)
,而不是
super().from_dict(row)

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