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

发布于 2021-01-29 15:00:49

有以下代码:

>>> 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模块的一部分。

关注者
0
被浏览
105
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    详细的“会发生什么”

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

    该函数为类命名空间添加了额外的值,__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第一次开发,巨蟒也没有上课装饰。

    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
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看