Создание объектов производного класса в базовом классе - python - PullRequest
2 голосов
/ 22 февраля 2020

У меня есть абстрактный класс с именем IDataStream, и у него есть один метод. Я создаю две реализации для этого абстрактного класса под названием IMUDataStream, GPSDataStream. В будущем есть возможность добавить еще одну реализацию абстрактного класса IDataStream. У меня есть другой класс под названием DataVisualizer, который визуализирует все данные, извлекаемые различными классами DataStream.

В будущем, если я добавлю другую реализацию DataStream абстрактного класса IDataStream, мне не следует изменять класс DataVisualizer для визуализации данных. Есть ли способ создать объекты всех производных классов класса IDataStream, добавить его в список, выполнить итерацию по списку и использовать его для вызова методов, которые дадут мне данные?

Обратите внимание, что я новичок в python и шаблонах проектирования. Пытаюсь выучить. Это может быть полный тупой вопрос и полное безумие. У меня действительно есть требование для этого. Если это может быть достигнуто с помощью шаблона проектирования, я прошу читателя указать мне на материал. Помощь высоко ценится. Спасибо!

#!/usr/bin/env python3

from abc import ABC, abstractmethod

class IDataStream(ABC):
    def get_data(self):
        pass           

class IMUDataStream(IDataStream):
    def __init__(self):
        self.__text = "this is IMU data"

    def get_data(self):
        print(self.__text)

class GPSDataStream(IDataStream):
    def __init__(self):
        self.__text = "this is GPS data"

    def get_data(self):
        print(self.__text)

class DataVisualizer:
    def __init__(self):
        # somehow create objects of all derived classes of IDataStream here and call the get_data() function
        # even if I add another derived class in the future. I should not be modifying the code here

Ответы [ 2 ]

0 голосов
/ 13 марта 2020

Во-первых, вы, вероятно, хотите, чтобы метод get_data - возвращал данные, а не печатал их (иначе он выполняет свою собственную визуализацию). Это может делать то, что вы хотите. Следующий код выяснит все подклассы IDataStream, создаст экземпляр экземпляра класса, если он не является абстрактным классом, вызовет метод get_data в экземпляре и добавит возвращаемые значения в list:

#!/usr/bin/env python3

from abc import ABC, abstractmethod

class IDataStream(ABC):
    @abstractmethod # you probably ment to add this
    def get_data(self):
        pass

class IMUDataStream(IDataStream):
    def __init__(self):
        self.__text = "this is IMU data"

    def get_data(self):
        return self.__text

class GPSDataStream(IDataStream):
    def __init__(self):
        self.__text = "this is GPS data"

    def get_data(self):
        return self.__text


def is_abstract(cls):
    return bool(getattr(cls, "__abstractmethods__", False))


def get_all_non_abstract_subclasses(cls):
    all_subclasses = []
    for subclass in cls.__subclasses__():
        if not is_abstract(subclass):
            all_subclasses.append(subclass)
        all_subclasses.extend(get_all_non_abstract_subclasses(subclass))
    return all_subclasses


class DataVisualizer:
    def __init__(self):
        data =  [cls().get_data() for cls in get_all_non_abstract_subclasses(IDataStream)]
        print(data)

dv = DataVisualizer()

Отпечатки:

['this is IMU data', 'this is GPS data']
0 голосов
/ 22 февраля 2020

То, что вы просите, - это найти все экземпляры объектов, которые находятся в памяти, и затем отфильтровать их только для определенного класса / подкласса / родительского класса / чего угодно, взгляните на это переполнение стека вопрос относительно того, как получить все текущие объекты и методы из памяти.

Тем не менее ... Каждый раз, когда вам нужно спросить себя, как найти ВСЕ экземпляры чего-то ГЛОБАЛЬНО в памяти, вы должны остановить себя и спрашивает (что, кажется, вы сделали, так что, слава Богу), есть ли лучший / более простой способ?

В большинстве случаев вы хотели бы сделать визуализатор данных независимым, чтобы он только потреблял данные поток (который указывается во время построения), см. ниже:

ds = myDataStream()

vis = myDataVisualizer(ds)
vis.show() # or whatever

или

ds = myDataStream()

vis = myDataVisualizer()
vis.show(ds)

Если вы хотите, чтобы визуализатор данных был агностированностью данных c, во время выполнения (например, есть данные, поступающие из нескольких источников), то у вас есть пара вариантов. Добавьте методы для удаления и добавления источников данных, или вы можете связать их вместе, используя что-то вроде шаблона «производитель-потребитель», используя Очереди и процессы (Вот как я это делаю).

НО Если вы действительно должны управлять своей собственной памятью целиком (например, с помощью карты, кучи или чего-то еще) Тогда есть шаблоны проектирования, которые могут вам помочь:

  • Фабрика
  • Абстрактная Фабрика
  • Декоратор
  • Или, может быть, какой-то другой, посмотрите на каталог по refactoring.guru
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...