调用依赖方法的大多数python方法

调用依赖方法的大多数python方法,python,Python,我有一个包含几个方法的类——每个方法都设置了一些内部状态,通常需要先调用其他方法来准备阶段。 典型的调用如下所示: c = MyMysteryClass() c.connectToServer() c.downloadData() c.computeResults() 在某些情况下,只调用connectToServer()和downloadData()(甚至只调用connectToServer()) 问题是:当以错误的顺序调用这些方法时(或者换句话说,当内部状态尚未准备好执行任务时),这些方法

我有一个包含几个方法的类——每个方法都设置了一些内部状态,通常需要先调用其他方法来准备阶段。 典型的调用如下所示:

c = MyMysteryClass()
c.connectToServer()
c.downloadData()
c.computeResults()
在某些情况下,只调用connectToServer()和downloadData()(甚至只调用connectToServer())

问题是:当以错误的顺序调用这些方法时(或者换句话说,当内部状态尚未准备好执行任务时),这些方法应该如何运行

我看到两种解决办法:

  • 他们应该抛出一个异常
  • 他们应该在内部调用正确的前一个方法
目前我正在使用第二种方法,因为它允许我编写更少的代码(我可以只编写c.computersults(),并且知道如果需要,将调用另外两个方法)。另外,当我多次呼叫他们时,我不必跟踪已经呼叫的内容,因此我可以避免多次重新连接或下载

另一方面,从调用方的角度来看,第一种方法似乎更容易预测,并且可能不太容易出错

当然,混合解决方案也有可能:抛出和异常,并添加另一层具有内部状态检测和正确调用以前方法的方法。但这似乎有点过分了


您的建议?

他们应该抛出异常。正如Python的禅宗所说:
显式优于隐式。
而且,就这一点而言,
错误永远不应该以静默的方式传递。除非显式静默。
如果调用方法的顺序不正确,那是程序员的错误,您不应该试图通过猜测它们的意思来修复。您可能会意外地以一种看似有效的方式掩盖一个疏忽,但实际上并不能准确反映程序员的意图。(那个程序员可能是你的未来。)

如果这些方法通常一个接一个地被调用,您可以考虑通过添加一个新方法来对它们进行排序,只需连续调用这些方法即可。这样,您就可以使用该方法,而不必担心出错


请注意,以这种方式处理内部状态的类有时会被调用,但实际上通常不是必需的。根据您的用例和应用程序其余部分的需要,您最好使用函数并实际将连接对象等从一个方法传递到另一个方法,而不是使用类来存储内部状态。例如,见。这只是一个需要考虑的事情,而不是必须的;许多通情达理的人不同意停止写作课背后的理论。

你应该写例外。编写异常以使代码更易于理解是一种很好的编程实践,原因如下:

  • 你所描述的符合“例外”的字面描述——这是正常程序的例外
  • 如果您构建了某种变通方法,您可能会遇到“意大利面代码”=错误
  • 当您或其他人稍后返回并阅读此代码时,如果您不提供提示,说明这些方法的无序执行是一种例外,则很难理解 以下是一个很好的来源:

    正如我的计算机科学教授经常说的,“好的程序员可以编写计算机可以阅读的代码,但伟大的程序员可以编写人类和计算机都可以阅读的代码。”


    我希望这会有所帮助。

    如果可能的话,您应该明确依赖关系

    例如:

    c = MyMysteryClass()
    connection = c.connectToServer()
    data = c.downloadData(connection)
    results = c.computeResults(data)
    

    这样,即使您不知道库是如何工作的,也只有一个顺序可以调用方法。

    由于您的建议侧重于“显式而非隐式”主题,我将尝试指出您遗漏的细节:问题是-这并不完全是解决方法和对无效调用顺序的反应。对于内部链接,这就像缓存一样——我调用我想要的方法,我知道只有那些以前没有调用过的方法才会在内部运行。添加异常需要我添加另一层代码,以确保我没有重新连接或重新下载数据。例如:我在某个地方传递了一个类的对象,但不知道它已经是什么状态。现在,我可以安全地调用computersults(),一切都会正常工作。对于异常,我需要在try-except中关闭它,在出现故障时调用downloadData()(在try-except中它本身应该关闭,以最终调用connectToServer()),也许解决方案是有两个类:一个“低级”完成工作并引发异常,另一个是“缓存包装器”它跟踪状态以及在每种情况下需要调用的内容。但它变得过于复杂了……或者,也许只是两套方法?与simpleDownloadData()和smartDownloadData()类似,第一个链抛出异常,第二个链调用connectToServer()?