This design is based on descriptors, specifically non-data descriptors. Every function happens to be a non-data descriptor by defining a __get__ method:
>>> def foo():
... pass
...
>>> foo.__get__
<method-wrapper '__get__' of function object at 0x7fa75be5be50>
When you have an expression x.y in your code, this means the attribute y is being looked up on the object x. The specific rules are explained here, and one of them is concerned with y being a (non-)data descriptor stored on the class of x (or any subclass). The following is an example:
>>> class Foo:
... def test(self):
... pass
...
Here Foo.test looks up the name test on the class Foo. The result is the function as you would define in the global namespace:
>>> Foo.test
<function Foo.test at 0x7fa75be5bf70>
However, as we have seen above, every function is also a descriptor, so if you look up test on an instance of Foo, it will call the descriptor's __get__ method to compute the result:
>>> f = Foo()
>>> f.test
<bound method Foo.test of <__main__.Foo object at 0x7fa75bf56b20>>
We can obtain a similar result by manually invoking Foo.test.__get__:
>>> Foo.test.__get__(f, type(f))
<bound method Foo.test of <__main__.Foo object at 0x7fa75bf56b20>>
This mechanism is what ensures that the instance (typically denoted via self) is passed as the first argument to instance methods. The descriptor returns a bound method (bound to the instance on which the lookup was performed) rather than the original function. This bound method inserts the instance as the very first parameter when being called. Every time you do Foo.test a new bound-method object is returned and hence their ids differ.
The situation with classmethods is similar where Foo.test.__get__(None, Foo) is called. The only difference is that for instances object.__getattribute__ is called while for classes type.__getattribute__ takes precedence.
>>> class Bar:
... @classmethod
... def test(cls):
... pass
...
>>> Bar.test
<bound method Bar.test of <class '__main__.Bar'>>
>>> Bar.__dict__['test'].__get__(None, Bar)
<bound method Bar.test of <class '__main__.Bar'>>