0
点赞
收藏
分享

微信扫一扫

python 接口

探头的新芽 04-03 23:15 阅读 2

接口(interface)主要进行 API 的定义。它描述了一个应该实现需要的行为的类的方法 和属性的列表。这个描述不实现任何代码,只是为希望实现接口的任何类定义了显式契约。 任何类都可以以任何想要的方式实现一个或多个接口。

虽然 Python 更喜欢使用鸭子类型,而不是显式接口定义,但有时后者可能更好。例如, 显式接口定义使框架更容易定义接口上的功能。

好处是类是松耦合的,这被认为是一个好的做法。例如,为了执行给定的过程,类 A 不依赖于类 B,而是依赖于接口 I.类 B 实现了 I,但它可以是任何其他类。

在许多静态类型的语言中都内置了对这种技术的支持,例如 Java 或 Go。接口允许函 数或方法限制实现给定接口的可接受参数对象的范围,无论它来自哪个类。这比将参数限 制到给定类型或其子类更灵活。它像鸭子类型行为的显式版本:Java 使用接口在编译时验 证类型安全性,而不是在运行时使用鸭子类型将事物绑定在一起。

与 Java 相比,Python 有一个完全不同的类型原理,所以它没有本地支持的接口。无论 如何,如果你想对应用程序接口有更明确的控制,通常有两种解决方案可供选择。

• 使用一些添加接口概念的第三方框架。

• 使用一些高级语言特性来构建处理接口的方法。 (1)使用 zope.interface

你可以使用一些框架在 Python 中构建显式接口。最值得注意的一个是 Zope 项目的一

部分。就是 zope.interface 包。虽然,现在,Zope 不像以前那么流行,zope.interface 包仍然是 Twisted 框架的主要组件之一。

zope.interface 包的核心类是 Interface 类。你可以通过子类化来显式地定义一 个新的接口。让我们假设我们要为矩形的每个实现定义强制性接口,如下所示:

      from zope.interface import Interface, Attribute

      class IRectangle(Interface):

          width = Attribute("The width of rectangle")

          height = Attribute("The height of rectangle")

def area():

""" 返回矩形的面积

"""

def perimeter(): """ 返回矩形的周长

"""

使用 zope.interface 定义接口时需要注意的一些重要事项如下。

• 接口的常用命名约定是使用 I 作为名称后缀。

• 接口的方法不能使用 self 参数。

• 由于接口不提供具体的实现,它应该只包含空方法。你可以使用 pass 语句,抛出

NotImplementedError,或提供 docstring(首选)。

• 接口还可以使用 Attribute 类指定所需的属性。 当你定义了这样的约定时,你可以定义新的具体类,为我们的 IRectangle 接口提供实

现。为了做到这一点,你需要使用 implementer()类装饰器,并实现所有定义的方法和 属性如下所示:

      @implementer(IRectangle)

      class Square:

""" 使用 rectangle 接口的正方形实现 """

def __init__(self, size): self.size = size

          @property

          def width(self):

return self.size

          @property

          def height(self):

              return self.size

          def area(self):

              return self.size ** 2

          def perimeter(self):

              return 4 * self.size

      @implementer(IRectangle)

      class Rectangle:

""" 矩形的具体实现

"""

def __init__(self, width, height):

              self.width = width

              self.height = height

          def area(self):

              return self.width * self.height

          def perimeter(self):

              return self.width * 2 + self.height * 2

通常,接口定义了具体实现需要满足的约定。此设计模式的主要优点是能够在使用对象 之前验证约定和实现之间的一致性。使用普通的鸭子类型方法,只有当运行时缺少属性或方 法时,才会发现不一致。使用 zope.interface,你可以使用 zope.interface.verify 模块中的两个方法内省实际实现,已在早期发现不一致。

• verifyClass(interface,class_object):这将验证类对象是否存在方法 以及它们的签名的正确性,无需查找属性。

• verifyObject(interface,instance):它验证方法,它们的签名以及实际 对象实例的属性。

 由于我们已经定义了我们的接口和两个具体的实现,让我们在以下交互式会话中验证

它们的约定:

   >>> from zope.interface.verify import verifyClass, verifyObject

   >>> verifyObject(IRectangle, Square(2))

   True

   >>> verifyClass(IRectangle, Square)

True

   >>> verifyObject(IRectangle, Rectangle(2, 2))

   True

   >>> verifyClass(IRectangle, Rectangle)

   True

没有什么令人印象深刻。Rectangle 和 Square 类仔细地遵循定义的约定,所以除 了成功验证之外,没有什么可做的了。但是当我们犯错误时会发生什么?让我们看一个没 有提供完整的 IRectangle 接口实现的两个类的例子如下所示:

      @implementer(IRectangle)

      class Point:

def __init__(self, x, y): self.x = x

self.y = y

      @implementer(IRectangle)

      class Circle:

def __init__(self, radius): self.radius = radius

          def area(self):

              return math.pi * self.radius ** 2

          def perimeter(self):

              return 2 * math.pi * self.radius

举报

相关推荐

0 条评论