>> type(list.append), list.a-6ren">
gpt4 book ai didi

python - "wrapper"和 "method"描述符之间的区别?

转载 作者:太空狗 更新时间:2023-10-29 20:29:58 24 4
gpt4 key购买 nike

我正在编写一段使用内省(introspection)查找类的“未绑定(bind)方法”的代码,并且惊讶地看到内置类型的两种不同类型的描述符:

>>> type(list.append), list.append
(<class 'method_descriptor'>, <method 'append' of 'list' objects>)
>>> type(list.__add__), list.__add__
(<class 'wrapper_descriptor'>, <slot wrapper '__add__' of 'list' objects>)

Searching the docs结果非常有限但很有趣:

  1. A note in the inspect moduleinspect.getattr_static不解析描述符并包含可用于解析它们的代码。
  2. an optimization made in python 2.4声称method_descriptorwrapper_descriptor更有效率但没有解释它们是什么:

    The methods list.__getitem__(), dict.__getitem__(), and dict.__contains__() are now implemented as method_descriptor objects rather than wrapper_descriptor objects. This form of access doubles their performance and makes them more suitable for use as arguments to functionals: map(mydict.__getitem__, keylist).

性能上的差异让我很感兴趣,显然存在差异所以我去寻找更多信息。

这些类型都不在模块 types 中:

>>> import types
>>> type(list.append) in vars(types).values()
False
>>> type(list.__add__) in vars(types).values()
False

使用 help没有提供任何有用的信息:

>>> help(type(list.append))
Help on class method_descriptor in module builtins:

class method_descriptor(object)
| Methods defined here:
|
<generic descriptions for>
__call__, __get__, __getattribute__, __reduce__, and __repr__
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __objclass__
|
| __text_signature__

>>> help(type(list.__add__))
Help on class wrapper_descriptor in module builtins:

class wrapper_descriptor(object)
| Methods defined here:
|
<generic descriptions for>
__call__, __get__, __getattribute__, __reduce__, and __repr__
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __objclass__
|
| __text_signature__

Searching the internet只得出关于“什么是描述符”的结果或对所涉及的特定类型的模糊引用。

所以我的问题是:

<class 'method_descriptor'> 之间的实际区别是什么?和 <class 'wrapper_descriptor'> ?

最佳答案

这是一个实现细节。在 C 级别,像 list 这样的内置类型通过 PyMethodDef 结构数组按名称定义像 append 这样的方法,而像 __add__ 的定义更间接。

__add__ 对应于类型的 tp_as_sequencenb_add 中的两个槽 sq_concat 中的任意一个中的函数指针在类型的 tp_as_number 中。如果一个类型定义了其中一个槽,Python 会生成一个 wrapper_descriptor 包装该槽,用于 Python 级 API 的 __add__ 方法。

类型槽和 PyMethodDef 结构所需的包装有点不同;例如,两个槽可以对应一种方法,或者一个槽可以对应六种方法。插槽也不携带它们的方法名称,而方法名称是 PyMethodDef 中的字段之一。由于这两种情况需要不同的代码,Python 使用不同的包装器类型来包装它们。

想看代码的话,method_descriptorwrapper_descriptor都在Objects/descrobject.c中实现了, 在 Include/descrobject.h 中有 struct typedefs .您可以在 Objects/typeobject.c 中看到初始化包装器的代码,其中 PyType_Readywrapper_descriptor 委托(delegate)给 add_operators,将 method_descriptor 委托(delegate)给 add_methods

关于python - "wrapper"和 "method"描述符之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37820527/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com