在基类中创建派生类的对象-python

时间:2020-02-21 23:20:18

标签: python python-3.x oop design-patterns

我有一个名为IDataStream的抽象类,它有一个方法。我为此抽象类(称为IMUDataStream,GPSDataStream)创建了两个实现。将来可能会添加IDataStream抽象类的另一种实现。我还有另一个名为DataVisualizer的类,该类可可视化由不同DataStream类提取的所有数据。

将来,如果我添加IDataStream抽象类的另一个DataStream实现,则不应修改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 :(得分:0)

您要问的是能够找到内存中的所有实例化对象,然后仅针对特定的类/子类/父类/任何对象对其进行过滤,请看一下有关此stack-overflow question的内容如何从内存中获取所有当前对象和方法。

这就是说...每当您不得不问自己如何在内存中全局查找某个对象的所有实例时,您应该停止自己并问(好像您这样做,因此倍感荣幸)是否有更好/更轻松的方法方式吗?

大多数时候,您希望使数据可视化器独立,以便仅使用数据流(在构造期间指定),请参见下文:

ds = myDataStream()

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

ds = myDataStream()

vis = myDataVisualizer()
vis.show(ds)

如果希望数据可视化工具与数据无关,例如在运行时(例如,数据来自多个来源),则有两种选择。添加用于删除和添加数据源的方法,或者,您可以使用Queues and Processes使用生产者-消费者模式之类的东西将它们链接在一起(这就是我的方法)。

但是,如果您真的必须完全管理自己的内存(例如通过映射或堆)。然后,有一些设计模式可以为您提供帮助:

  • 工厂
  • 抽象工厂
  • 装饰器
  • 或者也许是其他人,请查看目录refactoring.guru

答案 1 :(得分:0)

首先,您可能希望方法get_data返回数据而不是 print (否则它会进行自己的可视化处理)。这可能会做您想要的。以下代码将找出IDataStream的所有子类,如果不是抽象类,则实例化该类的实例,在该实例上调用方法get_data并将返回值附加到{{1 }}:

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()
相关问题