This is because 'unbound methods' don't exist in Python 3.
In Python 3000, the concept of unbound methods has been removed, and the expression "A.spam" returns a plain function object. It turned out that the restriction that the first argument had to be an instance of A was rarely helpful in diagnosing problems, and frequently an obstacle to advanced usages --- some have called it "duck typing self" which seems an appropriate name.
(Source)
In Python 2.x, we had bound methods and unbound methods. A bound method was bound to an object, meaning that when it was called, it passed the object instance as the first variable (self
, normally). An unbound method was one where the function was a method, but without a instance it belonged to - it would throw an error if something other than an object instance was passed in to the method.
Now, in 3.x, this has been changed. Instead of bound/unbound methods, when you request a method of an object, it returns the function object, but wrapped in a wrapper function that passes the instance variable in. This way there is no need to make a distinction between bound and unbound methods - bound methods are wrapped, unbound are not.
To clarify the difference:
2.x:
a = A()
f = A.method # f is an unbound method - you must pass an instance of `A` in to it as the first argument.
f = a.method # f is a bound method, bound to the instance `a`.
3.x:
a = A()
f = A.method # f is a function
f = a.method # f is a wrapped function with it's first argument filled with `a`.
a.method
can be thought of as:
def method-wrapper():
A.method(a)
For more on this, check out Guido's blog - the history of Python.
Edit:
So, the reason this all applies is that, here, __ne__()
has not been overridden - it's at a default state, which is an identity check, implemented in C (line 980ish). The wrapper is there to provide the method with the above functionality.