[Python] Python: Calling a class method of the superclass explicitly works yet calling it with...

Discussão em 'Python' iniciado por Stack, Dezembro 20, 2024.

  1. Stack

    Stack Membro Participativo

    I am trying to call the class method of the superclass (Sample) but when I do I get a type error. I can fix this by explicitly calling the Sample.from_dict(row) rather than super().from_dict(row). I just don't understand the difference:

    Superclass:

    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}")



    Subclass:

    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}")


    Usage:

    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)


    This works but when I replace the line: sample = Sample.from_dict(row) With: sample = super().from_dict(row) I get TypeError: KnownSample.__init__() missing 1 required positional argument: 'species'

    Continue reading...

Compartilhe esta Página