Python method-wrapper type?

It appears that the type <method-wrapper ..> is used by CPython for methods implemented in C code. Basically the type doesn’t wrap another method. Instead it wraps a C-implemented function as an bound method. In this way <method-wrapper> is exactly like a <bound-method> except that it is implemented in C.

In CPython there are two special types related to this.

  • <slot wrapper> Which (at least) wraps a C-implemented function. Behaves like an <unbound method> in CPython 2 (at least sometimes) or a <function> in CPython 3
  • <method-wrapper> Which wraps a C-implemented function as an bound method. Instances of this type have an __self__ attribute__ which is used as first argument when it is called.

If you have a <slot wrapper> you bind it to an object with __get__ to get an <method-wrapper>:

# returns a <slot_wrapper> on both CPython 2 and 3
sw = object.__getattribute__  

# returns a <method-wrapper>
bound_method = sw.__get__(object()) 

# In this case raises AttributeError since no "some_attribute" exists.
bound_method("some_attribute")  

You can call __get__ on any function-like object in Python to get an <bound method> or <method-wrapper>. Note __get__ on both of these types will simply return self.

Python 3

The type object in CPython 3 have C-implementations for both __ne__ and __eq__, and any of the other comparison operators. Thus object.__ne__ returns a <slot wrapper> for this operator. Likewise object().__ne__ returns a <method-wrapper> which can be used to compare the this object.

Since you have not defined __ne__ in your class you get a bound method (as <method-wrapper>) which is the C-implemented function for instance of object (included derived instances). My bet is that this C function will check if you have defined any __eq__, call this, and then not the result.

Python 2 (not asked but answered)

Python 2 behaves significantly different here. Since we have the concept of unbound methods. which require that you call them with the proper first-argument type, both <slot wrapper> and <method-wrapper> have an __objclass__ which is the type the first-argument must be an instance of.

More over: Python 2 does not have any implementations of comparisons operators for the object type. Thus object.__ne__ is not a function to compare objects. Rather, interesting, the type type which is the metaclass of object does have an C-implemented __ne__ operator. Thus you get an bound method from object.__ne__ that will try to compare the type object with any other type (or object).

Thus object().__ne__ will actually fail with an AttributeError since object does not define any such method. Given that object() == object() actually works (giving False), I would guess that CPython 2 have special-cases in the interpreter for comparison of objects.
Once more we see that CPython 3 have cleaned up some less-fortunate implementation details of Python 2.

Leave a Comment