In Python 3 unbound methods were removed:
the "unbound method" type has entirely disappeared -- a method, until and unless it's bound, is just a function, without the weird "type-checking" unbound methods used to perform.
Example in Python 3
Some explanations on descriptors
How could that be that `a.f is not a.f`?
Each time you try to access a method using a dot (`a.func`) Python will look into `__dict__` dictionary of object `a` for an attribute name `func` . If it's not found there (in case of a method it's usually not there), Python will look into class's `__dict__` for the attribute `func`. `def` statement inside a class definition puts a function into class's `__dict__`, so it's there. So Python found the attribute `func` of function type. Then Python will see if the attribute is a descriptor. All functions on Python are objects implementing descriptor protocol - they are non-data descriptors, having `__get__` method. So when you access `a.func` Python will not return `func` at is is, but will return `A.__dict__['func'].__get__(a, A)` according to descriptor protocol. This means that `A.func is not a.func`, because `a.func` is a wrapper around `A.func`, and that `a.func is not a.func`, because each access to the method returns a new wrapper.
 This is true for methods, they being non-data descriptors:
Data and non-data descriptors differ in how overrides are calculated with respect to entries in an instance’s dictionary. If an instance’s dictionary has an entry with the same name as a data descriptor, the data descriptor takes precedence. If an instance’s dictionary has an entry with the same name as a non-data descriptor, the dictionary entry takes precedence.More info here: http://docs.python.org/3/howto/descriptor.html#descriptor-protocol
The method access thing implies more issues. It means that if you want to replace a method with another implementation on runtime (aka "monkey-patching"), you can do it in two ways. You can assign `A.func` another function and this will call your new `func` implementation in all existing and new instances of class `A` if you are access it via dot (`self.func()` or `obj.func()`, i.e. you haven't stored reference to the old implementation somewhere) or you haven't monkey-patched method only of that particular instance.
The code was highlighted using pygments