Python 3 has no unrelated methods. Forget the classmethod for a moment and look at this:
>>> class Foo: ... def baz(self): pass >>> Foo.baz <function __main__.baz>
In 2.x, this will be the <unbound method Foo.baz> , but 3.x has no unbound methods.
If you want to get a function from a related method, this is easy:
>>> foo = Foo() >>> foo.baz <bound method Foo.baz of <__main__.Foo object at 0x104da6850>> >>> foo.baz.__func__ <function __main__.baz>
Similar:
>>> class Foo: ... @classmethod ... def bar(cls): pass >>> Foo.bar <bound method type.bar of <class '__main__.Foo'>> >>> Foo.bar.__func__ <function __main__.bar>
In 2.x, everything is much more interesting, because in fact there are unrelated methods. Usually you donβt see an unbound classmethod , because the thing is that they are attached to the class at the time the class was created, instead of remaining unbound and then attached to each instance when creating the instance of the instance.
But really, an unrelated method is just an instancemethod whose im_self is None. So how can you do this:
class Foo(object): def baz(self): pass foo = Foo() bound_baz = foo.baz unbound_baz = new.instancemethod(bound_baz.im_func, None, bound_baz.im_class)
Note that bound_baz.im_func is the 2.x version of bound_baz.__func__ in 3.x, but that new.instancemethod does not have the 3.x equivalent.
The documentation states that new deprecated in favor of types , for 3.x compatibility, and in fact you can do it in 2.x:
unbound_baz = types.MethodType(bound_baz.im_func, None, bound_baz.im_class)
But this does not work in 3.x because MethodType does not accept the class parameter and does not allow its instance parameter to be None . And personally, when I do something explicitly 2.x-only and cannot port to 3.x, I think the use of new is clearer.
Anyway, given the class in 2.x, you can do this:
class Foo(object): @classmethod def bar(cls): pass bound_bar = Foo.bar unbound_bar = new.instancemethod(bound_bar.im_func, None, bound_bar.im_class)
If you print it, you will see:
<unbound method type.bar>
Or, using your example, with an old-style class:
class Foo: @classmethod def bar(cls): pass <unbound method classobj.bar>
And yes, maybe it's a bit of a hoax that im_class for classmethod for the old-style class classobj , although this is not Foo.__class__ , but it seems like the most reasonable way to get old-style and new-style classes that work similarly in all common use cases.