问题描述
具有此代码:
>>> 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
很明显,对zope.interface.implements
的调用以某种方式改变了类Foo
的属性和行为.
Obviously, the call of zope.interface.implements
in some way alters the properties and behavior of the class Foo
.
这是怎么发生的?如何在我的代码中使用这种方法?
How does this happen? How do I use this approach in my code?
示例代码是 zope.interface 的一部分>模块.
Example code is the part of zope.interface module.
推荐答案
详细的会发生什么"
zope.interface.implements()
函数检查框架堆栈并更改构造类的locals()
名称空间(python dict
). python class
语句中的所有内容都在该命名空间中执行,结果形成类主体.
The detailed "what happens"
The zope.interface.implements()
function inspects the frame stack and alters the locals()
namespace (a python dict
) of the class-in-construction. Everything within a class
statement in python is executed in that namespace, and the result forms the class body.
该函数为类命名空间__implements_advice_data__
添加了额外的值,其中包含一些数据(您已传递给该函数的接口以及classImplements
可调用的对象,这些将在以后使用.)
The function adds an extra value to the class namespace, __implements_advice_data__
with some data (the interfaces you've passed to the function, and the classImplements
callable, something that'll be used later on.
然后,通过在命名空间中添加(或更改先前存在的)__metaclass__
键,在有关类的元类中添加或链接.这样可以确保将来每次创建该类的实例时,都将首先调用现在安装的元类.
It then either adds or chains in a metaclass for the class in question, by adding the (or altering a pre-existing) __metaclass__
key in the namespace. This ensures that in the future, every time you create an instance of the class, the metaclass now installed will be called first.
实际上,这个元类(类顾问)有点曲解.首次创建实例后,它会再次删除本身.它只是在__implements_advice_data__
中指定的回调函数以及您传递给原始implements()
函数的接口一起调用,之后立即从类中删除__metaclass__
键,或将其替换为原始的__metaclass__
(它被调用以创建第一个类实例).回调会在其自身之后清除,它将从类中删除__implements_advice_data__
属性.
In fact, this metaclass (the class advisor) is a little devious; it removes itself again after the first time you create an instance. It simply calls the callback specified in the __implements_advice_data__
together with the interfaces you passed to the original implements()
function, right after it either deletes the __metaclass__
key from the class, or replaces it with the original __metaclass__
(which it called to create the first class instance). The callback cleans up after itself, it removes the __implements_advice_data__
attribute from the class.
总而言之,zope.interface.implements()
所做的全部工作是:
In summary, all the work zope.interface.implements()
does is:
- 添加传递的接口以及对类(
__implements_advice_data__
)中特殊属性的回调. - 确保使用特殊的元类在首次创建实例时调用该回调.
- Add the passed interfaces, together with a callback to a special attribute in the class (
__implements_advice_data__
). - Ensures that the callback is called the first time you create an instance, using a special metaclass.
最后,在道德上等同于定义这样的接口:
In the end, it's the moral equivalent of defining your interfaces like this:
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
的实例之外.
except that the last call is postponed until you first create an instance of Foo
.
zope.interface
最初开发时,Python还没有类装饰器.
When zope.interface
was first developed, Python did not yet have class decorators.
zope.interface.classImplements()
作为函数,并且zope.interface.implements()
调用 in 类类提供了关于类实现什么接口的更好文档.您可以将其放在类声明的顶部,并且每个人在查看该类时都可以看到这一重要信息.在 之后放置classImplements()
调用时,类声明几乎不那么清晰可见,对于长类定义而言,很容易将其完全遗漏掉.
zope.interface.classImplements()
needs to be called separately, as a function, after the class has been created, and a zope.interface.implements()
call within the class body provides better documentation about what interfaces a class implements. You can place it right at the top of a class declaration, and everyone can see this important piece of information when looking at the class. Having a classImplements()
call located after the class declaration is not nearly as visible and clear, and for long class definitions it is easily going to be missed altogether.
PEP 3129 确实向该语言添加了类装饰器,他们被添加到python 2.6和3.0; zope.interface
最早是在python 2.3(IIRC)时代开发的.
PEP 3129 finally did add class decorators to the language, and they were added to python 2.6 and 3.0; zope.interface
was first developed back in the days of python 2.3 (IIRC).
现在我们要做有类修饰符,zope.interface.implements()
已被弃用,您可以改用zope.interface.implementer
类修饰符:
Now that we do have class decorators, zope.interface.implements()
has been deprecated, and you can use the zope.interface.implementer
class decorator instead:
@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
这篇关于在类声明中如何调用函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!