【发布时间】:2018-05-17 15:55:00
【问题描述】:
我在以原则良好的面向对象方式组织我的代码时遇到了麻烦。
总结:我希望有两个单独的类,每个类都实现自己的功能(例如分别模拟和绘图),但以某种方式将它们组合起来(以可扩展的方式!)拥有一个实例实现它们的两个功能。
示例:假设我有一个生成数据的类
class DataSimulator():
def __init__(self, N):
self.N = N
self.result = None
def simulate(self):
self.result = range(self.N) #imagine lots of simulation code here
我还想绘制我的数据。我可以简单地将plot() 方法添加到DataSimulator 但是
- 我认为
DataPlotter应该是它自己独立的类,因为它的功能与DataSimulator的功能完全不同。
A. 我想出的一个选项是一个单独的类,它存储一个 DataSimulator 实例,然后根据需要绘制它
class DataPlotter():
def __init__(self, data_simulator_instance):
self.d = data_simulator_instance
def plot(self):
plt.plot(self.d.result) #e.g. using matplotlib
dataSim = DataSimulator(5)
dataPlt = DataPlotter(dataSim)
dataSim.simulate()
dataPlt.plot()
但是,为了使用这个范式;
- 我需要始终跟踪两个独立的紧密耦合对象。这似乎是不好的做法。我永远不会没有另一个,所以我想将它们的功能合二为一。
B. 我考虑让DataPlotter 继承自DataSimulator,如下所示:
class DataPlotter(DataSimulator):
def plot(self):
plt.plot(self.result)
dataPlt = DataPlotter(5)
dataPlt.simulate()
dataPlt.plot()
这很好,因为我现在只有一个实例可以满足我的所有需求,但这似乎仍然是错误的,因为:
-
DataPlotter实例执行模拟例程令人困惑 - 如果我写了
DataSimulatorVersion2,我就不能重复使用我的DataPlotter。
C.同样我也考虑过DataSimulator继承自DataPlotter
class DataPlotter():
def plot(self):
plt.plot(self.result)
class DataSimulator(DataPlotter):
def __init__(self, N):
self.N = N
self.result = None
def simulate(self):
#lots of simulation code here
self.result = range(self.N)
dataSim = DataSimulator(5)
dataSim.simulate()
dataSim.plot()
这解决了上面的第一个问题(我认为模拟器绘制数据是有意义的,但绘图仪模拟数据却不是)但是现在
- 如果我写一个
DataPlotterVersion2,我就不能重用DataSimulator - 在
DataPlotter中使用self.result而不保证变量存在似乎也是不好的做法。
我的问题:
- 是否有解决此问题的最佳实践方法? (我在顶部的摘要中写的实际上是我想要的,还是应该走完全不同的路线?)
- 我提出的问题(在要点中)是否真的有效?
【问题讨论】:
-
做了更多研究后,我发现这个讨论特别有帮助:groups.google.com/forum/#!topic/comp.lang.python/Gw_l5F6mpjY
标签: python class oop project-organization