python 中接口的实现
实际上,由于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