I was writing a code that finds "unbound methods" of a class using introspection and was surprised to see two different kinds of descriptors for builtin types:
>>> 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 turned up very limited but interesting results:
- A note in the inspect module that
inspect.getattr_static
doesn't resolve descriptors and includes a code that can be used to resolve them. - an optimization made in python 2.4 claiming that
method_descriptor
is more efficient thanwrapper_descriptor
but not explaining what they are:The methods
list.__getitem__()
,dict.__getitem__()
, anddict.__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)
.
The difference in performance quite intrigued me, clearly there is a difference so I went looking for additional information.
Neither of these types are in the module types
:
>>> import types
>>> type(list.append) in vars(types).values()
False
>>> type(list.__add__) in vars(types).values()
False
using help
doesn't provide any useful information:
>>> 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 only came up with results about "what is a descriptor" or vague references to the specific types involved.
So my question is:
What is the actual difference between <class 'method_descriptor'>
and <class 'wrapper_descriptor'>
?