实际上,由于python是动态语言,支持多继承,因此接口在语言层面,是没有的东东。

然后,在架构设计上,我们又需要这么一个东西,来规范开发人员的行为。

因此就有了zope.interface的诞生。

定义接口

继承 zope.interface.Interface即可,如下:

import zope.interface
class IFoo(zope.interface.Interface):
"""Foo blah blah"""
x = zope.interface.Attribute("""x blah blah""")
def bar(q, r=None):
"""bar blah blah"""

1. 接口不是类

>>> type(IFoo)
<class 'zope.interface.interface.InterfaceClass'>
>>> class A(object):
pass >>> type(A)
<type 'type'>

但能正常访问:__dict__ / __name__ / __module__ / __doc__ 等专有属性

2. 行为有点类似于字典

>>> list(IFoo)
['x', 'bar']
>>> IFoo.get('bar')
<zope.interface.interface.Method object at 0x0000000002B7B710>
>>> callable(IFoo.get('bar'))
True

3. 接口中的方法能自动获取签名

>>> IFoo['bar'].getSignatureString()
'(q, r=None)'

实现接口

在声明接口之前,有两个术语要说明下:

provide(提供接口)

对象实例(object)提供接口,接口详细描述/规范了对象的行为。

implement(实现)

类(可以抽象成工厂类)实现(implement)接口。

类一般不会提供(provide)接口。只有对象提供接口。【备注:此处属于术语概念,了解即可】

1. 实现接口:

a). 用类实现

>>> class Foo:
zope.interface.implements(IFoo)

有点诧异:没有报错!对象实例呢?

>>> f = Foo()

也没有报错!然后下面却报错了:

>>> IFoo['bar'](1)

Traceback (most recent call last):
File "<pyshell#85>", line 1, in <module>
IFoo['bar'](1)
File "C:\Python27\lib\site-packages\zope\interface\interface.py", line 616, in __call__
raise BrokenImplementation(self.interface, self.__name__)
BrokenImplementation: An object has failed to implement interface <InterfaceClass __main__.IFoo> The bar attribute was not provided.

问题:该如何在子类的实例中使用接口里面定义的方法?

如何规范开发人员的行为?

答案是:通过测试来发现对象或者类是否实现了定义的接口。通过代码测试来做。通过测试控制开发,似乎有点马后炮。

主要使用 zope.interface.verify 里面的 verifyObject 和 verifyClass方法。可以参考这里

>>> class IFoo(Interface):
x = Attribute("The X attribute")
def bar(q,r=None):
"""bar of interface""" >>> class Foo:
implements(IFoo) >>> from zope.interface.verify import verifyObject, verifyClass
>>> verifyObject(IFoo, Foo()) Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
verifyObject(IFoo, Foo())
File "C:\Python27\lib\site-packages\zope\interface\verify.py", line 105, in verifyObject
return _verify(iface, candidate, tentative, vtype='o')
File "C:\Python27\lib\site-packages\zope\interface\verify.py", line 62, in _verify
raise BrokenImplementation(iface, name)
BrokenImplementation: An object has failed to implement interface <InterfaceClass __main__.IFoo> The x attribute was not provided. >>> verifyClass(IFoo, Foo) Traceback (most recent call last):
File "<pyshell#14>", line 1, in <module>
verifyClass(IFoo, Foo)
File "C:\Python27\lib\site-packages\zope\interface\verify.py", line 102, in verifyClass
return _verify(iface, candidate, tentative, vtype='c')
File "C:\Python27\lib\site-packages\zope\interface\verify.py", line 62, in _verify
raise BrokenImplementation(iface, name)
BrokenImplementation: An object has failed to implement interface <InterfaceClass __main__.IFoo> The bar attribute was not provided.

  

b) 用实例变量实现:

>>> b= Foo()
>>> b = zope.interface.implementer(IFoo)(b)
>>> list(zope.interface.providedBy(b))
[<InterfaceClass __main__.IFoo>]

在python 2.6后,可以直接用修饰符,上面代码的等同代码如下:

>>> from zope.interface import implementer
>>> @implementer(IFoo)
class Foo:
pass >>> list(zope.interface.implementedBy(Foo))
[<InterfaceClass __main__.IFoo>]

  

2. 查看类实现了哪些接口

>>> list(zope.interface.implementedBy(Foo))
[<InterfaceClass __main__.IFoo>]

测试某接口是否由某类实现:

>>> IFoo.implementedBy(Foo)
True

3. 查看对象实例实现了哪些接口

>>> list(zope.interface.providedBy(f))
[<InterfaceClass __main__.IFoo>]

测试某接口是否由某对象提供

>>> IFoo.providedBy(f)
True

  

接口的继承

与python的类继承相似。又有所不同,接口继承不是深度优先,如下:

>>> import zope.interface
>>> class IBase(zope.interface.Interface):
def foo():
"""base foo doc""" >>> class IBase1(IBase):
pass >>> class IBase2(IBase):
def foo():
"""base2 foo doc""" >>> class ISub(IBase1, IBase2):
pass >>> ISub['foo'].__doc__
'base2 foo doc'

  

类的继承:

>>> class Base:
def foo(self):
print "base" >>> class Base1(Base):
pass >>> class Base2(Base):
def foo(self):
print "base2" >>> class Sub(Base1,Base2):
pass >>> Sub().foo()
base

  

python 中接口的实现的更多相关文章

  1. python接口自动化(九)--python中字典和json的区别(详解)

    简介 这篇文章的由来是由于上一篇发送post请求的接口时候,参数传字典(dict)和json的缘故,因为python中,json和dict非常类似,都是key-value的形式,为啥还要这么传参,在群 ...

  2. 使用sphinx自动提取python中的注释成为接口文档

    写好了代码,交付给他人使用的时候,查看代码固然可以了解各类和函数的功能细节,但接口文档能更方便的查找和说明功能.所以,一价与代码同步的接口文档是很有必要的.sphinx可以根据python中的注释,自 ...

  3. Python 中的面向接口编程

    前言 "面向接口编程"写 Java 的朋友耳朵已经可以听出干茧了吧,当然这个思想在 Java 中非常重要,甚至几乎所有的编程语言都需要,毕竟程序具有良好的扩展性.维护性谁都不能拒绝 ...

  4. python2.7高级编程 笔记二(Python中的描述符)

    Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解.这些特性包括列表/集合/字典推导式,属性(property).以及装饰器(decorator).对于大部分特性来说,这些" ...

  5. 用 ElementTree 在 Python 中解析 XML

    用 ElementTree 在 Python 中解析 XML 原文: http://eli.thegreenplace.net/2012/03/15/processing-xml-in-python- ...

  6. centos下python中添加easygui模块

    前提:python中要集成Tkinter,Tkinter模块("Tk 接口")是Python的标准Tk GUI工具包的接口.Tk和Tkinter可以在大多数的Unix平台下使用,同 ...

  7. 详解Python中的循环语句的用法

    一.简介 Python的条件和循环语句,决定了程序的控制流程,体现结构的多样性.须重要理解,if.while.for以及与它们相搭配的 else. elif.break.continue和pass语句 ...

  8. Python::re 模块 -- 在Python中使用正则表达式

    前言 这篇文章,并不是对正则表达式的介绍,而是对Python中如何结合re模块使用正则表达式的介绍.文章的侧重点是如何使用re模块在Python语言中使用正则表达式,对于Python表达式的语法和详细 ...

  9. Python中的threading

    Python中的threading RLock--重入锁 RLock在Python中的实现是对Lock的封装,具体在类中维护了一个重入次数的变量.一旦一个线程获得一个RLock,该线程再次要求获得该锁 ...

随机推荐

  1. Quartz.net的cron表达式

    写在前面 前面有一篇文章用到了quartz.net,在设置定时时间的时候,使用了cron表达式,这里记录几种常见设置方式,方便对照使用. 详情 在这篇文章:Quartz.Net在windows服务中的 ...

  2. 琐碎--选择文件夹(路径)+生产txt格式的log+数据库操作方式

    记录日常工作常用到的一些方法: 1 选择文件操作,并将文件的路径记录下来: OpenFileDialog ofd = new OpenFileDialog(); ofd.Multiselect = f ...

  3. 每天一个linux命令(44):ifconfig命令

    许多windows非常熟悉ipconfig命令行工具,它被用来获取网络接口配置信息并对此进行修改.Linux系统拥有一个类似的工具,也就是ifconfig(interfaces config).通常需 ...

  4. Oracle 索引

    索引是建立在数据库表中的某些列的上面,是与表关联的,可提供快速访问数据方式,但会影响增删改的效率:常用类型(按逻辑分类):单列索引和组合索引.唯一索引和非唯一索引. 什么时候要创建索引 (1)在经常需 ...

  5. 【CodeForces 621C】Wet Shark and Flowers

    题 There are n sharks who grow flowers for Wet Shark. They are all sitting around the table, such tha ...

  6. 【Matplotlib】 增加图例

    相关文档: Legend guide legend() command Legend API 控制图例入口 无参调用 legend() 会自动获取图例 handles 以及相关的 labels.其对应 ...

  7. RPD资料库创建(1)

    BI创建(数据)分析.仪表盘.报表前,都需要对数据进行建模,在oracle biee里称为创建“资料档案库”-该文件后缀为RPD,所以一般也称为创建RPD文件. 步骤: 1.从windows开始菜单里 ...

  8. 16.(转) Android之Support v4、v7、v13的区别和应用场景

    我们在项目中经常会碰到Android Support v4.v7和v13包兼容问题,所以有必要梳理下这些东西. google提供了Android Support Library package 系列的 ...

  9. CRUD之delete操作

    在公司的项目中delete之后的操作有两种处理方式 1.后台删除成功之后前台页面刷新 2.后台删除成功之后页面不刷新,但是数据所在的那个div会刷新一次 3.后台删除,页面上做了一个删除,删除的td没 ...

  10. 轻量级应用开发之(02)UIView

    一 控件 1.屏幕上的所有UI元素都叫做控件(也有叫做视图.组件)比如按钮(UIButton).文本(UILabel)都是控件. 2.控件的共同属性有哪些? 尺寸,位置,背景色 3. 苹果将控件的共同 ...