Выполнить родительский метод в унаследованных классах

У меня есть абстрактный класс Reader, который определяет метод reader, который будет реализовывать каждый из унаследованных классов. Я хочу выполнить метод _is_valid в начале каждой реализации метода reader, но я не хочу повторять код в каждом из классов или использовать декораторы.

import os

from abc import ABCMeta, abstractmethod

import pandas as pd


class Reader(ABCMeta):

    @abstractmethod
    def read(cls, f):
        raise NotImplementedError

    @staticmethod
    def _valid(f):
        return os.path.exists(f)


class CSVReader(Reader):
    def read(self, f):
        if not self._valid(f):
            return None
        else:
            return pd.read_csv(f).values


class XLSReader(Reader):
    def read(self, f):
        pass


class SHPReader(Reader):
    def read(self, f):
        pass

Есть идеи, как лучше всего это решить?

В методе read родительского класса добавьте вызов метода _valid и удалите raise NotImplemented. В ваших подклассах вам нужно будет добавить что-то вроде super().read(f). Я уверен, что вы не хотите использовать дескрипторы?

N Chauhan 10.08.2018 15:19

Что это лучше, чем использование декораторов, выполняющих проверку? Чего я пытаюсь избежать, так это повторения этой строки кода в других классах (немного, но форматов могут быть тысячи (JPG, PNG, DOC, TXT и т. д.). Это питонический способ сделать это? (Точно так же мне очень нравится то, что вы предлагаете)

fferrin 10.08.2018 15:23

Декоратор потребуется добавить в каждый конкретный подкласс. Поскольку вы хотите гарантировать, что каждый подкласс делает это, добавление его в базовый класс - лучший способ - вот для чего существует наследование. В Python абсолютно нормально для ABC быть конкретным частично. Встроенные ABC, такие как Set, Mapping и т.п., делают то же самое.

MisterMiyagi 10.08.2018 15:25

Хорошее объяснение. Но мне все равно нужно добавить super().read(f) в каждый подкласс, верно? Повторение этой строки меня очень беспокоит, но если это способ сделать в Python, то так и будет.

fferrin 10.08.2018 15:28
1
4
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш класс Reader может иметь открытый метод read, который он определяет, который вызывает _valid, затем _read.

from abc import ABC, abstractmethod

class Reader(ABC):  # Or metaclass=ABCMeta
    def read(self, f):
        if not self._valid(f):
            raise ValueError("Invalid")
        else:
            return self._read(f)
    @abstractmethod
    def _read(self, f)
        raise NotImplementedError
    @classmethod
    def _valid(cls, f)  # Subclasses can have more restrictive validations
        return os.path.exists(f)

Это интересно. Что мне тогда нужно сделать, так это реализовать метод _read в каждом из подклассов?

fferrin 10.08.2018 15:25

@ nikolat328 Да. Вы также можете определить методы _valid этих подклассов, и read подберет эти методы.

Patrick Haugh 10.08.2018 15:27

Отлично! Я не знаю, является ли хорошей практикой переопределение частных методов (не так ли?), Но это лучшее решение, которое я видел. Спасибо!

fferrin 10.08.2018 15:32

@ nikolat328 Что вы, вероятно, сделали бы, так это написать метод, который вызывает super()._valid(f), а затем выполняет некоторые собственные проверки. Я бы не стал слишком беспокоиться о различии между публичным и частным при написании классов Python, просто при их использовании. Также нет никаких серьезных причин, по которым _valid должен быть приватным.

Patrick Haugh 10.08.2018 15:36

Другие вопросы по теме