==========
Interfaces
==========
Interfaces are objects that specify (document) the external behavior
of objects that "provide" them. An interface specifies behavior
through:
- Informal documentation in a doc string
- Attribute definitions
- Invariants, which are conditions that must hold for objects that
provide the interface
Attribute definitions specify specific attributes. They define the
attribute name and provide documentation and constraints of attribute
values. Attribute definitions can take a number of forms, as we'll
see below.
Defining interfaces
===================
Interfaces are defined using Python class statements::
>>> 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"""
In the example above, we've created an interface, `IFoo`. We
subclassed `zope.interface.Interface`, which is an ancestor interface for
all interfaces, much as `object` is an ancestor of all new-style
classes [#create]_. The interface is not a class, it's an Interface,
an instance of `InterfaceClass`::
>>> type(IFoo)
<class 'zope.interface.interface.InterfaceClass'>
We can ask for the interface's documentation::
>>> IFoo.__doc__
'Foo blah blah'
and its name::
>>> IFoo.__name__
'IFoo'
and even its module::
>>> IFoo.__module__
'__main__'
The interface defined two attributes:
`x`
This is the simplest form of attribute definition. It has a name
and a doc string. It doesn't formally specify anything else.
`bar`
This is a method. A method is defined via a function definition. A
method is simply an attribute constrained to be a callable with a
particular signature, as provided by the function definition.
Note that `bar` doesn't take a `self` argument. Interfaces document
how an object is *used*. When calling instance methods, you don't
pass a `self` argument, so a `self` argument isn't included in the
interface signature. The `self` argument in instance methods is
really an implementation detail of Python instances. Other objects,
besides instances can provide interfaces and their methods might not
be instance methods. For example, modules can provide interfaces and
their methods are usually just functions. Even instances can have
methods that are not instance methods.
You can access the attributes defined by an interface using mapping
syntax::
>>> x = IFoo['x']
>>> type(x)
<class 'zope.interface.interface.Attribute'>
>>> x.__name__
'x'
>>> x.__doc__
'X blah blah'
>>> IFoo.get('x').__name__
'x'
>>> IFoo.get('y')
You can use `in` to determine if an interface defines a name::
>>> 'x' in IFoo
True
You can iterate over interfaces to get the names they define::
>>> names = list(IFoo)
>>> names.sort()
>>> names
['bar', 'x']
Remember that interfaces aren't classes. You can't access attribute
definitions as attributes of interfaces::
>>> IFoo.x
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'InterfaceClass' object has no attribute 'x'
Methods provide access to the method signature::
>>> bar = IFoo['bar']
>>> bar.getSignatureString()
'(q, r=None)'
TODO
Methods really should have a better API. This is something that
needs to be improved.
Declaring interfaces
====================
Having defined interfaces, we can *declare* that objects provide
them. Before we describe the details, lets define some terms:
*provide*
We say that objects *provide* interfaces. If an object provides an
interface, then the interface specifies the behavior of the
object. In other words, interfaces specify the behavior of the
objects that provide them.
*implement*
We normally say that classes *implement* interfaces. If a class
implements an interface, then the instances of the class provide
the interface. Objects provide interfaces that their classes
implement [#factory]_. (Objects can provide interfaces directly,
in addition to what their classes implement.)
It is important to note that classes don't usually provide the
interfaces that they implement.
We can generalize this to factories. For any callable object we
can declare that it produces objects that provide some interfaces
by saying that the factory implements the interfaces.
Now that we've defined these terms, we can talk about the API for
declaring interfaces.
Declaring implemented interfaces
--------------------------------
The most common way to declare interfaces is using the implements
function in a class statement::
>>> class Foo:
... zope.interface.implements(IFoo)
...
... def __init__(self, x=None):
... self.x = x
...
... def bar(self, q, r=None):
... return q, r, self.x
...
... def __repr__(self):
... return "Foo(%s)" % self.x
In this example, we declared that `Foo` implements `IFoo`. This means
that instances of `Foo` provide `IFoo`. Having made this declaration,
there are several ways we can introspect the declarations. First, we
can ask an interface whether it is implemented by a class::
>>> IFoo.implementedBy(Foo)
True
And we can ask whether an interface is provided by an object::
>>> foo = Foo()
>>> IFoo.providedBy(foo)
True
Of course, `Foo` doesn't provide `IFoo`, it implements it::
>>> IFoo.providedBy(Foo)
False
We can also ask what interfaces are implemented by an object::
>>> list(zope.interface.implementedBy(Foo))
[<InterfaceClass __main__.IFoo>]
It's an error to ask for interfaces implemented by a non-callable
object::
>>> IFoo.implementedBy(foo)
Traceback (most recent call last):
...
TypeError: ('ImplementedBy called for non-factory', Foo(None))
>>> list(zope.interface.implementedBy(foo))
Traceback (most recent call last):
...
TypeError: ('ImplementedBy called for non-factory', Foo(None))
Similarly, we can ask what interfaces are provided by an object::
>>> list(zope.interface.providedBy(foo))
[<InterfaceClass __main__.IFoo>]
>>> list(zope.interface.providedBy(Foo))
[]
We can declare interfaces implemented by other factories (besides
classes). We do this using a Python-2.4-style decorator named
`implementer`. In versions of Python before 2.4, this looks like::
>>> def yfoo(y):
... foo = Foo()
... foo.y = y
... return foo
>>> yfoo = zope.interface.implementer(IFoo)(yfoo)
>>> list(zope.interface.implementedBy(yfoo))
[<InterfaceClass __main__.IFoo>]
Note that the implementer decorator may modify it's argument. Callers
should not assume that a new object is created.
Using implementer also works on callable objects. This is used by
zope.formlib, as an example.
>>> class yfactory:
... def __call__(self, y):
... foo = Foo()
... foo.y = y
... return foo
>>> yfoo = yfactory()
>>> yfoo = zope.interface.implementer(IFoo)(yfoo)
>>> list(zope.interface.implementedBy(yfoo))
[<InterfaceClass __main__.IFoo>]
XXX: Double check and update these version numbers:
In zope.interface 3.5.2 and lower, the implementor decorator can not
be used for classes, but in 3.6.0 and higher it can:
>>> Foo = zope.interface.implementer(IFoo)(Foo)
>>> list(zope.interface.providedBy(Foo()))
[<InterfaceClass __main__.IFoo>]
Note that class decorators using the @implementor(IFoo) syntax are only
supported in Python 2.6 and later.
Declaring provided interfaces
-----------------------------
We can declare interfaces directly provided by objects. Suppose that
we want to document what the `__init__` method of the `Foo` class
does. It's not *really* part of `IFoo`. You wouldn't normally call
the `__init__` method on Foo instances. Rather, the `__init__` method
is part of the `Foo`'s `__call__` method::
>>> class IFooFactory(zope.interface.Interface):
..
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
共70个文件
py:44个
txt:18个
pkg-info:2个
python twisted framework zope interface python twisted framework zope interface python twisted framework zope interface
资源推荐
资源详情
资源评论
收起资源包目录
zope.interface-3.8.0.tar.gz (70个子文件)
zope.interface-3.8.0
PKG-INFO 13KB
README.txt 643B
build_ext_2.py 1KB
CHANGES.txt 9KB
build_ext_3.py 1KB
bootstrap.py 2KB
COPYRIGHT.txt 32B
tox.ini 233B
src
zope.interface.egg-info
PKG-INFO 13KB
requires.txt 58B
not-zip-safe 1B
SOURCES.txt 2KB
top_level.txt 5B
namespace_packages.txt 5B
dependency_links.txt 1B
zope
__init__.py 200B
interface
adapter.ru.txt 21KB
adapter.txt 14KB
README.txt 23KB
declarations.py 40KB
interface.py 23KB
adapter.py 22KB
ro.py 2KB
_zope_interface_coptimizations.c 44KB
_flatten.py 1KB
tests
test_odd_declarations.py 7KB
ifoo.py 851B
test_document.py 1KB
m1.py 812B
unitfixtures.py 4KB
test_adapter.py 11KB
odd.py 3KB
ifoo_other.py 851B
test_registry.py 36KB
test_sorting.py 2KB
dummy.py 793B
test_element.py 1KB
__init__.py 481B
test_advice.py 5KB
test_declarations.py 11KB
m2.py 689B
test_verify.py 4KB
foodforthought.txt 2KB
test_interface.py 18KB
verify.txt 3KB
interfaces.py 42KB
__init__.py 3KB
common
idatetime.py 20KB
tests
test_import_interfaces.py 928B
test_idatetime.py 2KB
__init__.py 61B
basemapping.py 4KB
interfaces.py 4KB
__init__.py 61B
sequence.py 5KB
mapping.py 3KB
human.ru.txt 10KB
advice.py 7KB
verify.py 4KB
README.ru.txt 33KB
registry.py 18KB
index.txt 359B
document.py 3KB
human.txt 6KB
exceptions.py 2KB
setup.cfg 59B
.bzrignore 79B
setup.py 5KB
LICENSE.txt 2KB
buildout.cfg 354B
共 70 条
- 1
资源评论
- sick_word2015-08-07还不错,算是满足的我的需求了
- dainiao012013-10-12我是在win下用 这个是linux下的 不知道怎么用
- 19842013-08-30安装试用了,可用于Twisted
弱水垂钓
- 粉丝: 25
- 资源: 14
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功