繁体   English   中英

如何在类声明中调用函数?

[英]How does the function that is called inside the class declaration?

有这个代码:

>>> 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的属性和行为。

这是怎么发生的? 如何在我的代码中使用此方法?

示例代码是zope.interface模块的一部分。

详细的“会发生什么”

zope.interface.implements()函数检查帧堆栈并改变构造类的locals()命名空间(python dict )。 python中的一个class语句中的所有内容都在该命名空间中执行,结果形成了类主体。

该函数为类名称空间__implements_advice_data__添加了一个额外的值, __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

阅读来源,卢克

http://svn.zope.org/zope.interface/trunk/src/zope/interface/declarations.py?rev=124816&view=markup

 def _implements(name, interfaces, classImplements): frame = sys._getframe(2) locals = frame.f_locals # Try to make sure we were called from a class def. In 2.2.0 we can't # check for __module__ since it doesn't seem to be added to the locals # until later on. if (locals is frame.f_globals) or ( ('__module__' not in locals) and sys.version_info[:3] > (2, 2, 0)): raise TypeError(name+" can be used only from a class definition.") if '__implements_advice_data__' in locals: raise TypeError(name+" can be used only once in a class definition.") locals['__implements_advice_data__'] = interfaces, classImplements addClassAdvisor(_implements_advice, depth=3) 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM