Python 类是否可以从不同的文件继承方法(或子类)?这是不是;蟒蛇的;?

Python 类是否可以从不同的文件继承方法(或子类)?这是不是;蟒蛇的;?,python,class,oop,inheritance,Python,Class,Oop,Inheritance,在尝试构建一个科学的Python包时,为了清晰起见,我的目标是将关键功能分离到不同的.py文件中。具体来说,在我看来,将一个模型的复杂数值计算拆分为一个python文件(比如“processing.py”),并将用于可视化的绘图例程拆分为另一个python文件(“plotting.py”)似乎是合乎逻辑的 为了方便和内存高效的使用,模型类应该能够继承所有绘图方法,使用户可以轻松访问这些方法,同时通过将科学数字代码与可视化代码分离,使代码易于维护和读取 我在下面概述了实现这一目标的愿景,但我正在努

在尝试构建一个科学的Python包时,为了清晰起见,我的目标是将关键功能分离到不同的.py文件中。具体来说,在我看来,将一个模型的复杂数值计算拆分为一个python文件(比如“processing.py”),并将用于可视化的绘图例程拆分为另一个python文件(“plotting.py”)似乎是合乎逻辑的

为了方便和内存高效的使用,模型类应该能够继承所有绘图方法,使用户可以轻松访问这些方法,同时通过将科学数字代码与可视化代码分离,使代码易于维护和读取

我在下面概述了实现这一目标的愿景,但我正在努力解决如何在Python/如果有更好的OOP风格可用的话实现这一点

例如,在plotting.py中:

class ItemPlotter(object):

    def visualisation_routine1(self):
        plt.plot(self.values)  # where values are to be acquired from the class in processing.py somehow
在processing.py中:

class Item(object):

    def __init__(self, flag):
        if flag is True:
            self.values = (1, 2, 3)
        else:
            self.values = (10, 5, 0)

        from plotting.py import ItemPlotter
        self.plots = ItemPlotter()
这将导致使用以下命令行:

 from processing.py import Item
 my_item = Item(flag=True)
 # Plot results
 my_item.plots.visualisation_routine1()
我的实际代码将比这更复杂,并且可能项将具有大型数据集的属性,因此我希望我需要避免复制这些属性以提高内存效率

请问,我的视力可能吗,或者甚至是一种蟒蛇式的方法? 有什么意见吗。欢迎使用面向对象或有效的方法来实现这一点

另外,我的目标是Py2.7和Py3的兼容性

为了方便和内存高效的使用,模型类应该能够继承所有绘图方法,使用户可以轻松访问这些方法,同时通过将科学数字代码与可视化代码分离,使代码易于维护和读取

正如Jon所指出的,您实际上是在描述组合,而不是继承(无论如何,这是一种方式)

实现所需功能的一种方法是创建一个抽象类,用于定义“项目绘图仪”的接口和
item
的实例。您可以允许
Item
的客户端轻松打印
Item
实例封装的数据,方法是将打印委托给注入的
ItemPlotter

这种方法允许每个类都尊重代码,并使代码更易于理解、维护和测试。如果愿意,可以在单独的Python模块中定义
Item
ItemPlotter

from abc import abstractmethod, ABC


class AbstractItemPlotter(ABC):
    @abstractmethod
    def plot(self, values):
        return


class ItemPlotter(AbstractItemPlotter):
    def plot(self, values):
        # plt.plot(values)
        print('Plotting {}'.format(values))
        pass


class Item(object):
    def __init__(self, flag: bool, plotter: AbstractItemPlotter):
        self._plotter = plotter
        if flag:
            self.values = (1, 2, 3)
        else:
            self.values = (10, 5, 0)

    def visualisation_routine1(self):
        self._plotter.plot(self.values)

if __name__ == '__main__':
    item = Item(flag=True, plotter=ItemPlotter())
    item.visualisation_routine1()
输出

绘图(1,2,3)
编辑


该代码使用Python 3.5.2进行了测试。我不能确定它是否能在Python 2.7中正常工作。

这既不是继承也不是子类化,而是组合。是的,可以使用其他地方类的实例作为属性,但是您仍然应该将导入放在文件的顶部。您能提供一个工作示例吗?当我尝试此操作时,我得到AttributeError:“ItemPlotter”对象没有属性“vales”。谢谢你的帮助。。。是的,没错,没有。因为,再一次,您不是子类化。在
项的实例中有一个
项绘图仪的实例
,但它们不是同一个对象(它们不共享
自身
)。也许
Item
应该继承自
ItemPlotter
,反之亦然。或者,您可以在实例化ItemPlotter时传递Item的实例(即
self
),或者在调用
visualization\u routine1
时传递该实例。另外请注意,创建例如
self.plotter=ItemPlotter(self.values)
实际上并不复制值,它只是意味着两个实例共享对同一对象的引用。但是,如果您希望
ItemPlotter
成为“类中的混合”,则需要
Item
来继承它。感谢您的帮助以及指向良好OOP样式的链接。这看起来很棒。我想知道为什么我们需要创建AbstractItemPlotter类——我是否需要将AbstractItemPlotter中ItemPlotter的每个方法都复制为“abstractmethod”才能工作?此外,我想知道你认为这与@Daniel Roseman在之前的帖子评论中的想法相比如何。是否使用self.plotter=ItemPlotter(self)简化plotter类的初始化,并在ItemPlotter init中保存对self的引用?Thanks@IanRoberts“我是否需要将AbstractItemPlotter中ItemPlotter的每个方法复制为一个“abstractmethod”以使其正常工作?”只有在实现之间可能有所不同的方法。通用方法可以在基类中实现。另见。至于第二个问题,Daniel的方法似乎是另一种体面的方法,尽管我不知道他是否真的打算将
ItemPlotter
存储在
Item
中。这会使课程更加紧密,这通常是不好的。