Найти - Пользователи
Полная версия: как в классе который наследует dict cоздать метод который надо обязательно переопределить в классе наследнике
Начало » Python для новичков » как в классе который наследует dict cоздать метод который надо обязательно переопределить в классе наследнике
1 2
vrabey
есть такой класс
class Data(dict):
    def __init__(self):
        super().__init__()
    def load(self, path):
        if self:
            self.clear()
        if not os.path.isfile(path):
            raise FileNotFoundError(
                _FILE_ASSERT_TEMPLATE.format(path))
        self.update(self.get_data(path))
    def get_data(self, path):
        raise TypeError(_METHOD_ERROR_ASSERT_TEMPLATE.format(Data.get_data.__name__))

метод get_data надо переопределить в наследнике
но хочу что бы исключение вызывалось при создании
объкта наследника а не при обращенни к методу, как сейчас

@abc.abstractmethod - так не работает при наследовании от dict


ayb
class Data(dict):
    def __init__(self):
        super().__init__()
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "get_data"):
            raise AttributeError("you need to implement get_data in"
                                 " {} class".format(cls.__name__))
        if not hasattr(getattr(cls, "get_data"), "__call__"):
            raise AttributeError("get_data must be instance method")
        return super().__new__(cls, *args, **kwargs)
vrabey
наверное не правильно объяснил
класс Data нужен что бы от него наследоваться
метод get_data в нём как раз определён для того что бы в классе наследнике его тоже определили обязательно.
class Data(dict):
    def __init__(self):
        super().__init__()
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "get_data"):
            raise AttributeError("you need to implement get_data in"
                                 " {} class".format(cls.__name__))
        if not hasattr(getattr(cls, "get_data"), "__call__"):
            raise AttributeError("get_data must be instance method")
        return super().__new__(cls, *args, **kwargs)
    def get_data(self):
        # возвращает объект словаря
        pass
class JsonData(Data):
    def __init__(self):
        super().__init__()
# должен быть переопределён метод get_data
data = JsonData()
попытка создать экземпляр JsonData должна вызвать исключение
в смысле хотелось бы
FishHook
class Data(dict):
    def __init__(self):
        super().__init__()
        assert hasattr(self, "get_data")
vrabey
FishHook
class Data(dict): def __init__(self): super().__init__() assert hasattr(self, “get_data”)

так исключение вызывается если в Data нет атрибута “get_data”.
но этот атрибут в классе Data как раз точно есть. Мне надо что бы
исключение вызвалось, если нет атрибута “get_data” в классе наследнике,
что бы ниже код вызвал исключение.
или я что то совсем не правильно делаю ?
——————————
класс Data - это заготовка что бы на его основе сделать другой(ие)
классы которые наследуют метод load
но что бы всё это работало надо переопределить метод get_data, потому что способ получить данные
в разных классах может быть разный но возвращать должны какой то один тип



class Data(dict):
    def __init__(self):
        super().__init__()
        assert hasattr(self, "get_data")
    def load(self, path):
        # здесь исползуется get_data
         pass
    def get_data(self):
        # возвращает объект словаря
        pass
class JsonData(Data):
    def __init__(self):
        super().__init__()
d = JsonData()
ayb
vrabey
наверное не правильно объяснилкласс Data нужен что бы от него наследоватьсяметод get_data в нём как раз определён для того что бы в классе наследнике его тоже определили обязательно.

Так а зачем Вы предоставляете реализацию в базовом классе и требуете чтобы наследники её предопределяли ?
При таком подходе не нужно определять даже минимально ( с использованием pass ) методы, которые должны реализовывать наследники.

class Data(dict):
    def __init__(self):
        super().__init__()
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "get_data"):
            raise AttributeError("you need to implement get_data in"
                                 " {} class".format(cls.__name__))
        if not hasattr(getattr(cls, "get_data"), "__call__"):
            raise AttributeError("get_data must be instance method")
        return super().__new__(cls, *args, **kwargs)
    def some_method(self):
        print(self.get_data())
class P(Data):
    def get_data(self):
        return 1
a = P()
a.some_method()
1
vrabey
идея была такая:
есть класс
import json
class DataJson(dict):
    def __init__(self):
        super().__init__()
    def load(self, path):
        with open(path, "r") as obj:
            self.update(json.load(obj))
class Level:
    def __init__(self, data_obj, path):
        self.data = data_obj()
        self.data.load(path)
if __name__ == '__main__':
    path = "path.json"
    level = Level(DataJson, path)
    print(level.data)

но предположим что в будущем я буду использовать не json а например shelve хранилище
то мне надо будет Реализовать класс ShelveData с методом load.
хотел сделать базовый класс с общими методами от которого можно было наследовать
ну например проверка isFile или если файл пуст …
не получается
как делают в таких случаях?






ayb
vrabey
но предположим что в будущем я буду использовать не json а например shelve хранилище

Ну реализуете shelve хранилище а json можно будет выкинуть. Зачем нужен неиспользуемый класс ? Выделять общий функционал в базовый класс нужно когда у Вас в программе используются два похожих класса, которые незначительно различаются.
vrabey
ayb
Зачем нужен неиспользуемый класс
vrabey
хотел сделать базовый класс с общими методами от которого можно было наследовать
ну например проверка isFile или если файл пуст …
у них всё должно быть общее кроме способа получения настроек из файла
и сохранения
ayb
Я понимаю ситуацию так - Вы используете в программе класс который представляет работу с json хранилищем, затем ( как Вы пишите ) нужно будет использовать shelve хранилище. Если shelve будет ВМЕСТО json, то смысла выделять часть функционала в базовый класс нет. Если shelve будет использоваться ВМЕСТЕ с json, смысл есть. Вам показали как запретить наследникам инстанцироваться без реализации необходимых методов. Только базовый класс не должен реализовывать эти методы.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB