为什么在Python标准contextlib中使用type(x).__ enter __(x)而不是x .__ enter __()?

发布于 2021-01-29 14:09:40

contextlib.py,我看到ExitStack类正在呼叫__enter__()经由类型的对象方法(type(cm)),而不是直接方法调用给定对象(cm)。

我不知道为什么或为什么不。

例如,

  • 发生错误时,它能否提供更好的异常跟踪?
  • 它只是特定于某些模块作者的编码风格吗?
  • 它对性能有好处吗?
  • 它可以避免一些带有复杂类型层次结构的工件/副作用吗?
关注者
0
被浏览
241
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    首先,这就是您执行操作时发生的事情with something,而不仅仅是contextlib在类型上查找特殊方法。另外,值得注意的是,其他特殊方法也会发生同样的情况:例如,a + b结果为type(a).__add__(a, b)

    但是为什么会发生呢?这是一个经常在python-dev和python-ideas邮件列表上引发的问题。当我说“经常”时,我的意思是“经常”。

    最后一个是:缺少核心功能:+- / | &不要调用

    getattr*

    Eliminate特殊方法查找

    以下是一些有趣的观点:

    当前的行为是设计使然-特殊方法在对象类上的位置为槽,而不是实例属性。这允许解释器绕过正常实例属性查找过程中的几个步骤。

    (资源)

    值得注意的是,这种行为比这更神奇。即使在类,隐特殊方法查找旁路抬头__getattr____getattribute__元类的。因此,特殊的方法查找不仅仅是发生在类而不是实例上的普通查找。这是一个完全魔术的查找,不会在任何级别使用常规的attribute-
    access-customization挂钩。

    (资源)

    此行为也记录在参考文档中:特殊方法查找,其中说:

    __getattribute__()以这种方式绕过机器为解释器内的速度优化提供了很大的空间,但以牺牲一些特殊方法的灵活性为代价(特殊方法必须在类对象本身上设置,以便由解释器一致地调用)

    简而言之, 性能是主要关注的问题 。但是,让我们仔细看看。

    type(obj).__enter__()和之间有什么区别obj.__enter__()

    当您编写时obj.attrtype(obj).__getattribute__('attr')将被调用。Looks的默认实现会在实例字典(即)和类名称空间中进行__getattribute__()查找,否则将调用。attr``obj.__dict__``type(obj).__getattr__('attr')

    现在,这是一个快速的解释,我省略了一些细节,但是,它应该使您了解属性查找的复杂程度以及其查找速度。短路特殊方法查找肯定会提高性能,因为obj.__enter__()以“经典”方式查找可能太慢。



知识点
面圈网VIP题库

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

去下载看看