如果一个对象依赖于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
类的创建失败?
答案 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