- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在contextlib.py ,我看到 ExitStack 类正在通过类型对象 (type(cm)
) 调用 __enter__()
方法,而不是直接调用给定对象 (cm)
)。
我想知道为什么或为什么不。
例如,
最佳答案
首先,当您使用某些东西
时会发生这种情况,不仅仅是contextlib
会在类型上查找特殊方法。此外,值得注意的是,其他特殊方法也会发生同样的情况:例如a + b
结果为 type(a).__add__(a, b)
。
但为什么会这样呢?这是一个经常在 python-dev 和 python-ideas 邮件列表中引发的问题。当我说“经常”时,我的意思是“非常经常”。
最后一个是这些:Missing Core Feature: + - * / | & do not call getattr和 Eliminating special method lookup .
这里有一些有趣的点:
The current behaviour is by design - special methods are looked up as slots on the object's class, not as instance attributes. This allows the interpreter to bypass several steps in the normal instance attribute lookup process.
It is worth noting that the behavior is even more magical than this. Even when looked up on the class, implicit special method lookup bypasses
__getattr__
and__getattribute__
of the metaclass. So the special method lookup is not just an ordinary lookup that happens to start on the class instead of the instance; it is a fully magic lookup that does not engage the usual attribute-access-customization hooks at any level.
此行为也记录在引用文档中:Special method lookup ,它说:
Bypassing the
__getattribute__()
machinery in this fashion provides significant scope for speed optimisations within the interpreter, at the cost of some flexibility in the handling of special methods (the special method must be set on the class object itself in order to be consistently invoked by the interpreter).
简而言之,性能是主要关注点。但让我们仔细看看这个。
type(obj).__enter__()
和 obj.__enter__()
有什么区别?
当您编写 obj.attr
时,将调用 type(obj).__getattribute__('attr')
。 __getattribute__()
的默认实现在实例字典(即 obj.__dict__
)和类命名空间中查找 attr
,如果失败, 调用 type(obj).__getattr__('attr')
。
现在,这是一个快速的解释,我省略了一些细节,但是它应该让您了解属性查找可以有多复杂,它可以变得多慢。短路特殊方法查找肯定会提供性能改进,因为以“经典”方式查找 obj.__enter__()
可能太慢了。
关于python - 为什么 `type(x).__enter__(x)` 而不是 Python 标准上下文库中的 `x.__enter__()`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34490998/
我是一名优秀的程序员,十分优秀!