Python Zope接口的用途?
我已经开始在代码中使用Zope接口,到目前为止,它们实际上只是文档。我使用它们来指定类应该拥有哪些属性,在适当的类中显式实现它们,并在我期望的地方显式检查它们。这很好,但是如果可能的话,我希望他们做更多的工作,比如实际验证类是否实现了接口,而不仅仅是验证我说过的类是否实现了接口。我已经阅读了ZopeWiki好几次了,但是仍然看不到界面比我现在所做的更多的用途。所以,我的问题是,您还可以使用这些接口,以及如何使用这些接口。< p>我从未使用过Zope接口,但是您可能会考虑编写一个,它在初始化时检查对接口的类成员,如果没有实现一个方法,则会引发运行时异常。Python Zope接口的用途?,python,interface,zope,zope.interface,Python,Interface,Zope,Zope.interface,我已经开始在代码中使用Zope接口,到目前为止,它们实际上只是文档。我使用它们来指定类应该拥有哪些属性,在适当的类中显式实现它们,并在我期望的地方显式检查它们。这很好,但是如果可能的话,我希望他们做更多的工作,比如实际验证类是否实现了接口,而不仅仅是验证我说过的类是否实现了接口。我已经阅读了ZopeWiki好几次了,但是仍然看不到界面比我现在所做的更多的用途。所以,我的问题是,您还可以使用这些接口,以及如何使用这些接口。< p>我从未使用过Zope接口,但是您可能会考虑编写一个,它在初始化时检查
使用Python,您没有其他选择。可以使用“编译”步骤检查代码,也可以在运行时动态检查代码。您可以实际测试对象或类是否实现了接口。 为此,您可以使用
verify
模块(您通常会在测试中使用它):
接口还可用于设置和测试不变量。
您可以在此处找到更多信息:
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)
>>> 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'
现在我们可以用它来解耦a.py和b.py。b.py不再实例化Greeter类,而是请求提供IGreeter接口的实用程序。并且a.py将声明Greeter类实现该接口:
>>> from zope.interface import Interface
>>> class IGreeter(Interface):
... def greet():
... """ Gives a greeting. """
(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'
在我工作的地方,我们使用接口,这样我们就可以使用ZCA或,这是一个使用
Interface
s制作可交换和可插拔组件的整体框架。我们使用ZCA,这样我们就可以处理各种各样的每客户端定制,而不必使用我们的软件,也不必让所有的每客户端位弄乱主树。不幸的是,Zope wiki通常是不完整的。有一个很好的,但简洁的解释,大部分的ZCA的特点,在其上
我不使用Interface
s来检查类是否实现了给定接口的所有方法。理论上,当您向接口添加另一个方法时,这可能会很有用,以检查您是否记得将新方法添加到实现该接口的所有类中。就我个人而言,我更喜欢创建一个新的接口
,而不是修改一个旧接口。修改旧的接口
通常是一个非常糟糕的主意,因为它们已经发布到pypi或您的组织的其他部分
关于术语的简要说明:类实现接口
s,对象(类的实例)提供接口
s。如果要检查接口
,可以编写ISomething.implementedBy(SomeClass)
或ISomething.providedBy(someu对象)
因此,下面是ZCA有用的例子。让我们假设我们正在写一个博客,使用ZCA将其模块化。我们将为每篇文章提供一个BlogPost
对象,它将提供一个IBlogPost
接口,所有这些都是在我们方便的dandymy.blog
egg中定义的。我们还将博客的配置存储在BlogConfiguration
对象中,这些对象提供IBlogConfiguration
。以此为出发点,我们可以实现新的功能,而无需触及my.blog
下面是使用ZCA可以做的事情的示例列表,无需更改基本my.blog
egg。我或我的同事已经在real for client项目上完成了所有这些工作(并发现它们很有用),尽管当时我们没有实现博客:这里的一些用例可以通过其他方式更好地解决,比如打印CSS文件
向提供IBlogPost
的所有对象添加额外视图(BrowserView
s,通常使用browser:page
指令注册)。我可以制作一个my.blog.printable
egg。该egg将为IBlogPost
注册一个名为print
的浏览视图,该视图通过一个设计用于生成打印效果良好的HTML的浏览器来呈现博客文章。然后,BrowserView
将出现在URL/path/to/blogpost/@@print
Zope中的事件订阅机制。假设我想发布RSS提要,我想提前生成它们,而不是根据请求生成。我可以创建一个my.blog.rss
egg。在该egg中,我将为提供IBlogPost
的对象上提供(zope.lifecycleevent.interfaces.IObjectModified
)的事件注册订阅服务器。每当提供IBlogPost
的任何内容的属性发生更改时,该订阅者都会被调用,我可以使用它来更新博客文章应该出现在其中的所有RSS提要
在这种情况下,最好在每个修改博客文章的BrowserView
末尾发送一个IBlogPostModified
事件,因为IObjectModified
在每个属性更改时都会发送一次,这对于性能来说可能太频繁了
适配器。适配器实际上是从一个接口到另一个接口的“强制转换”。适用于编程语言极客:Zope adapte