【问题标题】:Creating objects of derived class in base class - python在基类中创建派生类的对象 - python
【发布时间】:2020-02-21 23:20:18
【问题描述】:

我有一个名为 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

【问题讨论】:

  • 听起来您正在寻找工厂模式。我建议你研究一下。

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


【解决方案1】:

您要问的是能够找到内存中的所有实例化对象,然后将它们过滤为仅特定类/子类/父类/无论什么,看看这个stack-overflow question 关于如何从内存中获取所有当前的对象和方法。

也就是说......任何时候你必须问自己如何在内存中找到全局某事物的所有实例,你应该停下来问自己(看起来你做了,所以荣誉)有没有更好/更容易怎么办?

大多数时候,您希望使数据可视化器独立,以便它只使用数据流(在构造过程中指定),见下文:

ds = myDataStream()

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

ds = myDataStream()

vis = myDataVisualizer()
vis.show(ds)

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

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

【讨论】:

    【解决方案2】:

    首先,您可能希望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']
    

    【讨论】:

      猜你喜欢
      • 2020-03-17
      • 2015-08-10
      • 1970-01-01
      • 2020-08-06
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多