我试图调用超类(示例)的类方法,但是当我这样做时,我收到类型错误。 我可以通过显式调用 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'
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)