我已经开始在我的代码中使用Zope接口,截至目前,它们实际上只是文档。我使用它们来指定类应具有的属性,在适当的类中显式实现它们,并在我期望的位置显式检查它们。这很好,但我希望他们在可能的情况下做更多的事情,比如实际验证该类是否已经实现了接口,而不仅仅是验证我已经说过该类实现了接口。我已经阅读了几次zope wiki,但仍然看不到比我目前正在做的更多的接口使用。所以,我的问题是你还可以使用这些接口,以及如何将它们用于更多接口。
答案 0 :(得分:51)
答案 1 :(得分:23)
您实际上可以测试您的对象或类是否实现了您的界面。
为此,您可以使用verify
模块(通常在测试中使用它):
>>> from zope.interface import Interface, Attribute, implements
>>> class IFoo(Interface):
... x = Attribute("The X attribute")
... y = Attribute("The Y attribute")
>>> class Foo(object):
... implements(IFoo)
... x = 1
... def __init__(self):
... self.y = 2
>>> from zope.interface.verify import verifyObject
>>> verifyObject(IFoo, Foo())
True
>>> from zope.interface.verify import verifyClass
>>> verifyClass(IFoo, Foo)
True
接口也可用于设置和测试不变量。 您可以在此处找到更多信息:
答案 2 :(得分:19)
Zope接口可以提供一种有用的方法来解耦两段不应相互依赖的代码。
假设我们有一个知道如何在模块a.py中打印问候语的组件:
>>> class Greeter(object):
... def greet(self):
... print 'Hello'
需要在模块b.py中打印问候语的一些代码:
>>> Greeter().greet()
'Hello'
这种安排使得在不触及b.py(可能分布在单独的包中)的情况下更换处理问候语的代码变得很困难。相反,我们可以引入第三个模块c.py来定义IGreeter接口:
>>> from zope.interface import Interface
>>> class IGreeter(Interface):
... def greet():
... """ Gives a greeting. """
现在我们可以用它来解耦a.py和b.py.而不是实例化Greeter类,b.py现在将要求提供IGreeter接口的实用程序。并且a.py将声明Greeter类实现该接口:
(a.py)
>>> from zope.interface import implementer
>>> from zope.component import provideUtility
>>> from c import IGreeter
>>> @implementer(IGreeter)
... class Greeter(object):
... def greet(self):
... print 'Hello'
>>> provideUtility(Greeter(), IGreeter)
(b.py)
>>> from zope.component import getUtility
>>> from c import IGreeter
>>> greeter = getUtility(IGreeter)
>>> greeter.greet()
'Hello'
答案 3 :(得分:2)
我从未使用过Zope接口,但你可能会考虑编写一个metaclass,它在初始化时会根据接口检查类的成员,如果没有实现某个方法,则会引发运行时异常。 / p>
使用Python,您没有其他选择。要么有一个“编译”步骤来检查你的代码,要么在运行时动态检查它。