详细的“发生了什么”
该zope.interface.implements()
函数检查帧堆栈并更改构造中的类的locals()
名称空间(python )。python 语句中的dict
所有内容都在该命名空间中执行,结果形成类主体。class
该函数为类命名空间添加了一个额外的值,__implements_advice_data__
其中包含一些数据(您传递给函数的接口和classImplements
可调用对象,稍后将使用这些数据。
__metaclass__
然后,它通过在命名空间中添加(或更改预先存在的)键来为所讨论的类添加或链接元类。这样可以确保以后每次创建类的实例时,都会首先调用现在安装的元类。
事实上,这个元类(类顾问)有点狡猾;在您第一次创建实例后,它会再次自行删除。它只是在从类中删除键或将其替换为原始键(它调用它以创建第一个类实例)之后,简单地调用在__implements_advice_data__
您传递给原始函数的接口中指定的回调。回调会自行清理,它会从类中删除属性。implements()
__metaclass__
__metaclass__
__implements_advice_data__
短版
总之,所做的所有工作zope.interface.implements()
是:
- 添加传递的接口,以及对类 (
__implements_advice_data__
) 中特殊属性的回调。
- 确保在您第一次使用特殊元类创建实例时调用回调。
最后,它在道德上等同于像这样定义你的接口:
class Foo:
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
zope.interface.classImplements(Foo, IFoo)
除了最后一次调用被推迟到您第一次创建Foo
.
但为什么要走这么远?
最初开发时zope.interface
,Python 还没有类装饰器。
zope.interface.classImplements()
需要在创建类之后作为函数单独调用,并且类主体内zope.interface.implements()
的调用提供了关于类实现哪些接口的更好文档。您可以将它放在类声明的顶部,每个人在查看类时都可以看到这条重要信息。在类声明之后进行调用并不是那么明显和清晰,对于长类定义,很容易完全错过它。classImplements()
PEP 3129终于在语言中添加了类装饰器,它们被添加到 python 2.6 和 3.0;zope.interface
最初是在 python 2.3 (IIRC) 时代开发的。
现在我们确实有类装饰器,zope.interface.implements()
但已被弃用,您可以改用zope.interface.implementer
类装饰器:
@zope.interface.implementer(IFoo)
class Foo:
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