当前位置: 首页 > 面试题库 >

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

柴茂材
2023-03-14
问题内容

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

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

例如,

  • 发生错误时,它能否提供更好的异常跟踪?
  • 它只是特定于某些模块作者的编码风格吗?
  • 它对性能有好处吗?
  • 它可以避免一些带有复杂类型层次结构的工件/副作用吗?

问题答案:

首先,这就是您执行操作时发生的事情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__()以“经典”方式查找可能太慢。



 类似资料:
  • 基于此,我认为我应该完全开始在中使用

  • 问题内容: 考虑以下示例: 我不确定Java语言规范中是否有一项规定要加载变量的先前值以便与右侧()进行比较,该变量应按照方括号内的顺序进行计算。 为什么第一个表达式求值,而第二个表达式求值?我本来希望先被评估,然后再与自身()比较并返回。 这个问题与Java表达式中子表达式的求值顺序不同,因为这里绝对不是“子表达式”。需要 加载 它以进行比较,而不是对其进行“评估”。这个问题是特定于Java的,

  • 这个问题与Java表达式中子表达式的求值顺序不同,因为在这里肯定不是“子表达式”。需要加载它进行比较,而不是“求值”。这个问题是特定于Java的,表达式来自一个真实的项目,而不是通常为棘手的面试问题而设计的牵强附会的不切实际的构造。它应该是比较和替换习语的一行替换 它比x86 CMPXCHG指令还要简单,因此在Java中应该使用更短的表达式。

  • 我最近遇到了几个错误,因为Numpy数组的形状是(x)-这些可以很容易地通过下面的代码段修复 但这确实让我想知道,为什么(x,)是1D数组的默认形状?

  • 问题内容: 我正在使用OWASP ZAP在我的本地主机上进行一些渗透测试,并且不断报告此消息: Anti-MIME-Sniffing标头X-Content-Type-Options未设置为’nosniff’ 此检查特定于Internet Explorer 8和Google Chrome。如果Content- Type标头未知,请确保每个页面都设置了Content-Type标头和X-CONTENT-

  • 我正在用OWASP ZAP在我的本地主机上做一些渗透测试,它不断报告这样的消息: 反MIME-嗅探标头X-Content-Type-Options未设置为“nosniff” 此检查针对Internet Explorer 8和Google Chrome。确保每个页面都设置一个Content-Type头,如果Content-Type头未知,则设置X-CONTENT-TYPE-OPTIONS 我不知道这