Python 属性解析开销
Python attribute resolution overhead
在属性解析期间,Python 是否检查每个属性是否存在于 class 中?这样的话,是不是开销很大?
例如检查属性a.x
。 Python 必须首先检查 A.__dict__["x"]
是否是数据描述符(因为它们覆盖了正常的属性查找),这意味着它应该检查整个 __mro__
的数据描述符。
这反过来意味着实例字典中的每个属性查找,都会在整个 class mro 中进行查找,这听起来像是一个巨大的开销。这是缓存了吗?即使是,是什么阻止了通过动态添加数据描述符来修改其中一个基本 classes?这个理论上的缓存将如何失效?
class 已经负责处理属性查找。但是,是的,要查找属性,会查询当前 class 和基础 classes,因为属性可能是数据描述符。
这是因为某些对象 特殊 ,因为它们可以绑定到实例或 class(descriptor、并且 如果它们是 data 描述符(支持设置或删除值的描述符),它们将覆盖实例上具有相同名称的任何属性。
所有这些都在 class 的 __getattribute__
method 的 C 实现中处理(通常继承自 object.__getattribute__)
,在 C 中,可以访问实例和 class 命名空间相对便宜。
请参阅 Descriptor HOWTO 以了解有关如何以及为什么这样做的更多详细信息。
在属性解析期间,Python 是否检查每个属性是否存在于 class 中?这样的话,是不是开销很大?
例如检查属性a.x
。 Python 必须首先检查 A.__dict__["x"]
是否是数据描述符(因为它们覆盖了正常的属性查找),这意味着它应该检查整个 __mro__
的数据描述符。
这反过来意味着实例字典中的每个属性查找,都会在整个 class mro 中进行查找,这听起来像是一个巨大的开销。这是缓存了吗?即使是,是什么阻止了通过动态添加数据描述符来修改其中一个基本 classes?这个理论上的缓存将如何失效?
class 已经负责处理属性查找。但是,是的,要查找属性,会查询当前 class 和基础 classes,因为属性可能是数据描述符。
这是因为某些对象 特殊 ,因为它们可以绑定到实例或 class(descriptor、并且 如果它们是 data 描述符(支持设置或删除值的描述符),它们将覆盖实例上具有相同名称的任何属性。
所有这些都在 class 的 __getattribute__
method 的 C 实现中处理(通常继承自 object.__getattribute__)
,在 C 中,可以访问实例和 class 命名空间相对便宜。
请参阅 Descriptor HOWTO 以了解有关如何以及为什么这样做的更多详细信息。