Python:如何处理无法正确初始化的类的方法调用?

时间:2011-12-08 21:18:40

标签: python oop coding-style module refactoring

如果一个对象依赖于Python不包含的模块(如win32api,gstreamer,gui工具包等),并且该模块中的类/函数/方法可能会失败,该对象应该做什么?

以下是一个例子:

import guimodule  # Just an example; could be anything

class RandomWindow(object):

    def __init__(self):
        try:
            self.dialog = guimodule.Dialog()  # I might fail
        except: guimodule.DialogError:
            self.dialog = None  # This can't be right

    def update(self):
        self.dialog.prepare()
        self.dialog.paint()
        self.dialog.update()

    # ~30 more methods

这个课程只是一个更大课程的一小部分(而且是不必要的,但有用的)。

假设我们有一个名为guimodule的虚构模块,其中有一个名为Dialog的类,可能无法实例化。如果我们的RandomWindow类已经说过30个操作此窗口的方法,那么检查if self.dialog is not None会很麻烦,并且会在常用的方法(如update方法中实现时减慢程序的速度在上面的例子中)。在.paint()上调用NoneType(当Dialog无法加载时)将引发错误,并使用所有原始方法制作虚拟Dialog课程和属性是荒谬的。

如何修改我的类以处理Dialog类的创建失败?

4 个答案:

答案 0 :(得分:3)

您应该允许__init__中引发的异常传播,而不是创建无效对象,以便以适当的方式处理错误。或者你可能提出了一个不同的例外。

另见Python: is it bad form to raise exceptions within __init__?

答案 1 :(得分:1)

您可能会发现它有两个子类很有用;一个使用该模块,另一个不使用。 “工厂”方法可以确定哪个子类是合适的,并返回该子类的实例。

通过子类化,您允许它们共享与该模块是否可用无关的代码。

答案 2 :(得分:0)

我同意“检查self.dialog是否不是None会很痛苦”,但我不同意它会减慢速度,因为如果存在self.dialog则会更慢。所以暂时忘记慢慢来。因此,一种处理方法是创建一个MockDialog,它在函数调用中不执行任何操作,例如。

class RandomWindow(object):

    def __init__(self):
        try:
            self.dialog = guimodule.Dialog()  # I might fail
        except: guimodule.DialogError:
            self.dialog = DummyDialog() # create a placeholder

class DummyDialog(object):
    # either list all methods or override __getattr__ to create a mock object

答案 3 :(得分:0)

如果考虑使用Pythons Dialog功能,制作一个虚拟的__getattr__类并不像你可能那样荒谬。以下虚拟实现完全符合您的需求:

class DummyDialog:
  def __getattr__(self, name):
    def fct(*args, **kwargs):
      pass
    return fct