Reputation: 61
Borrowing the implementation of an instance method from another class is straightforward, but how do I do it with a class method?
class A:
def im(self):
print(self.__class__.__name__)
@classmethod
def cm(cls):
print(cls.__name__)
class B:
im = A.im
cm = A.cm # line X
classmethod(cm)
B().im() # B - OK
B.cm() # A - not what I want
I also tried changing line X into cm = A.cm.__func__
, which caused TypeError: cm() missing 1 required positional argument: 'cls'
Upvotes: 1
Views: 1051
Reputation: 1121486
When you access A.cm
, you invoke the classmethod
object as a descriptor, which means it is already bound to the A
class. Unwrap it again:
class B:
cm = classmethod(A.cm.__func__)
The .__func__
attribute gives you access to the original function, so you can rewrap it with a new classmethod
call.
Alternatively, use the A.__dict__
mapping to get the actual classmethod itself, bypassing the descriptor calls:
class B:
cm = A.__dict__['cm']
Upvotes: 4
Reputation: 251355
You need:
class B:
im = A.im
cm = classmethod(A.cm.__func__)
When you access A.cm
, the resulting classmethod already "knows" that it belongs to A. If you want to rewrap it for a different class, you need to extract the underlying function with __func__
and then rewrap it with classmethod
.
Also, in your example, the line classmethod(cm)
does nothing, because you don't assign the result to anything.
Upvotes: 3