我正在编写一个使用内省查找类的“未绑定方法”的代码,并且惊讶地发现内置类型有两种不同的描述符:
>>> 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出现了非常有限但有趣的结果:
inspect.getattr_static
无法解析描述符并包含可用于解析它们的代码。method_descriptor
比wrapper_descriptor
更高效但不解释它们是什么:
方法
list.__getitem__()
,dict.__getitem__()
和dict.__contains__()
现在实现为 method_descriptor 对象,而不是 wrapper_descriptor 对象。 这种形式的访问使其性能提高了一倍,使它们更适合用作功能的参数: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'>
之间的实际差异是什么?
答案 0 :(得分:2)
这是一个实施细节。在C级别,像list
这样的内置类型通过append
结构数组按名称定义PyMethodDef
等方法,而__add__
等特殊方法更间接定义。
__add__
对应于类型&#39; s sq_concat
或tp_as_sequence
类型nb_add
中的两个广告位tp_as_number
中的任一个中的函数指针{1}}。如果某个类型定义了其中一个插槽,那么Python会为Python级API的wrapper_descriptor
方法生成一个__add__
包装槽。
类型槽和PyMethodDef
结构所需的包装有点不同;例如,两个时隙可以对应于一种方法,或者一个时隙可以对应于六种方法。插槽也不带有方法名称,而方法名称是PyMethodDef
中的字段之一。由于这两种情况需要不同的代码,因此Python使用不同的包装器类型来包装它们。
如果您想查看代码,method_descriptor
和wrapper_descriptor
都在Objects/descrobject.c
中实现,Include/descrobject.h
中包含struct typedefs。您可以在Objects/typeobject.c
中看到初始化包装器的代码,其中PyType_Ready
委托给add_operators
的{{1}}和wrapper_descriptor
的{{1}}。
答案 1 :(得分:0)
似乎 Dim ListView1 As ListView
ListView1 = New ListView()
和method_descriptor
是CPython中可用的一种callable。
它们之间的区别似乎很简单
wrapper_descriptor
显然用于内置方法
(在C中实现)对象:
method_descriptor
set.__dict__['union'].__class__
<class 'wrapper_descriptor'>
用于内置类型的运算符:
wrapper_descriptor
This is the place我找到了这些信息。