例如,我想在运行时检查给定对象是否具有方法foo()
和bar()
.
我的研究系统是用 python 3.6 构建的,它是高度参数化的,可以/应该接受任何类型的对象作为其内置模块的替代品。这个功能非常有用,因为使用这个系统的许多不同的学生可以很容易地研究不同的行为,而无需更改我系统的源代码。
问题是,如果他们错误地构建了模块,他们可能只有在整个实验结束后(可能是几个小时)才会发现这一点。
我正在寻找一种方法来在运行时的早期阶段检查他们的输入模块是否与特定接口匹配。甚至在实例化之前验证它会更好(当输入只是类型,而不是实例时)。例如some_interface.verify(MyClass)
.
解决方案
我在互联网上看到了很多解决方案(例如this),但没有一个适合:
最常见的解决方案 (
try/catch
) 只会在运行时失败,并且不适用于多守护程序系统,因为只有一个守护程序失败时很难关闭。检查
isinstance()
不会验证任何内容。情况可能更糟,因为开发人员可能忘记实现一个函数并使用基类实现,这可能不适合其当前实现。使用ABC(抽象基类)需要开发者继承基类。如果她/他没有这样做,实例化类时不会发出警告或错误。另一方面,如果开发人员确实实现了接口但没有继承自
base
,那么issubclass()
将返回 False。使用zope 接口是我的首选,但它有一些缺点:
- 它要求开发人员明确提及它正在实现接口。未能指定这将导致错误,尽管实际实现是正确的。
- 它无法在实例化之前验证模块。该
implementedBy()
方法只会检查声明的模块是否正在实现接口,但要实际验证它,您应该调用verifyObject()
实际实例。 - 它不支持自 python 3.5 以来添加的新类型功能
编辑:显然,zope 还支持通过调用隐式实现,verifyObject(YourInterface, obj, tentative=True)
这不会强制开发人员将类显式定义为接口的实现者。