In very large software projects, especially where the interaction with a lot of other software is expected and desired, it is necessary to develop well-specified application programming interfaces (APIs). We could think of APIs as standards of the frame- work, such as the RFC or POSIX standards. Once an interface is defined and made public, it should be very hard to change it. But an API is also useful inside a single software, known as internal API. Interfaces (in the sense we will use the term) provide a programmatic way to specify the API in a programming language.

在超大型的软件项目里,特别是那些期望与很多其他软件互动的,开发精确良好的应用程序接口(APIs)是非常必要的。我们可将APIs想象成一种框架,就像是RFC或POSIX标准那样。一旦定义了接口并且发布了,它就很难再被改变。但是,API在单体软件里也有用途,被看作是内部API。

While other modern programming languages like Java use interfaces as a native language feature, Python did not even have the equivalent of a formal interface until recently. Usually, in Python the API is defined by the class that implements it, and it was up to the documentation to create a formal representation of the API. This approach has many issues. Often developers changed the API of a class without realizing that they broke many other people's code. Programmed interfaces can completely resolve this issue, since alarm bells can be rung (via tests) as soon as an API breakage o ccurs. Here is a simple example of a Python interface (as used by the Zope pro ject):

当其他编程语言,例如Java,就将接口作为语言内部的特性,而直到最近Python才有了同等意义的正式的接口。通常,在Python里接口是通过类(class)来定义并实现的,并且它是通过文档来创建的API的表现。有很多关于这方面的文章。开发人员经常在没有意识到破坏了其他人的代码的情况下修改了类的API。编程接口可以完全解决这个问题,当一个API被破坏时警铃就会响起(通过测试)。 下面是一个简单的Python接口的例子(已经被使用在Zope项目中)

Line 1: We import the only two important objects from zope.interface here, the meta-class Interface and the class Attribute .

行 1:我们从zope.interface导入了2个重要的对象——元类Interface,类Attribute。

Line 3: We "misuse" the class declaration to declare interfaces as well. Note though, that interfaces are not classes and do not behave as such! Using Interface as base class will make this object an interface.

行 3:我们“误用”定义类的方式来定义接口。注意,虽然接口不是类并且也没有类的行为,但是当你把接口作为类的基类时,这个对象就变成了接口。

Line 4: In Zope 3 interfaces are the main source for API documentation, so that it is necessary to always write very descriptive doc strings. The interface doc string gives a detailed explanation on how objects implementing this interface are expected to function.

行 4:在Zope3里,这是接口的文档。所以,在这里写上明确的文档字符串是很必要的。接口文档字符串给出了实现接口功能的详细描述。

Line 6: The Attribute class is used to declare attributes in an interface. The constructor of this class only takes one string argument, which is the documenta- tion of this attribute. You might say now that there is much more meta-data that an attribute could have, such as the minimum value of an integer or the maximum length of a string for example. This type of extensions to the Attribute class are provided by another module called zope.schema, which is described in "Zope Schemas and Widgets (Forms)".

行 6:Attribute类是用来在接口中声明属性的。这个类的构造方法仅接受一个字符串参数,就是这个属性的文档字符串。现在你可能会说:“还有很多的元数据属性存在,例如整型的最小值或者字符串的最大长度等。”这一类型的扩展属性类是由另外一个模块提供的,叫zope.schema。我们将在“Zope模型和窗口部件(表单)”章节中阐述。

Line 8—9 & 11—12: Methods are declared using the def keyword as usual. The di erence is, though, that the first argument is not self. You only list all of the common arguments. The doc string is again used for do cumentation.

行 8-9和11-12:像通常那样使用def关键字来定义方法。不同的是第一个参数不是self。你只是列出了所有的公共参数。文档字符串依然作为文档来使用的。

Other than that, methods can contain anything you like; yet, Zope does not use anything else of the method content. If you use the zope.interface package apart from Zope 3, you could use the metho d body to provide formal descriptions of pre- and post conditions, argument types and return types.

除此之外,方法中可以包含任何你想要的东西,Zope不会使用方法里的任何内容。如果你在Zope3之外使用zope.interface包,那么你可以方法体来为先决条件、参数类型和返回类型提供一个正式的描述。

The above is a typical but not practical example of an interface. Since we use Python, it is not necessary to specify both, the attribute and the setter/getter meth- o ds. In this case we would usually just specify the attribute as part of the interface and implement it as a Python property if necessary.

上面是一个典型的但不实际的接口例子。既然我们使用Python,就没有必要同时为属性实现setter和getter方法。在这种情况下,我们通常可以将属性制定为接口的一部分并且用Python的属性来实现它,如果需要的话。