I found really good example how to add new method to the class dynamically (transplant class):
def say(host, msg):
print '%s says %s' % (host.name, msg)
def funcToMethod(func, clas, method_name=None):
setattr(clas, method_name or func.__name__, func)
class transplant:
def __init__(self, method, host, method_name=None):
self.host = host
self.method = method
setattr(host, method_name or method.__name__, self)
def __call__(self, *args, **kwargs):
nargs = [self.host]
nargs.extend(args)
return apply(self.method, nargs, kwargs)
class Patient:
def __init__(self, name):
self.name = name
if __name__ == '__main__':
jimmy = Patient('Jimmy')
transplant(say, jimmy, 'say1')
funcToMethod(say, jimmy, 'say2')
jimmy.say1('Hello')
jimmy.say2(jimmy, 'Good Bye!')
But I don't understand, how to modify it for adding static methods. Can someone help me?
I don't see a staticmethod here. The say
function is expecting two arguments, and the first argument, host
, appears to be the instance of the class.
So it seems like you are simply trying to attach a new method to a class. That can be done without funcToMethod or transplant:
def say(self, msg):
print '%s says %s' % (self.name, msg)
class Patient:
def __init__(self, name):
self.name = name
if __name__ == '__main__':
jimmy = Patient('Jimmy')
Patient.say = say
jimmy.say('Hello')
yields
Jimmy says Hello
If you did want to attach a staticmethod, then, as MartijnPieters answered, use the staticmethod
decorator:
def tell(msg):
print(msg)
if __name__ == '__main__':
jimmy = Patient('Jimmy')
Patient.tell = staticmethod(tell)
jimmy.tell('Goodbye')
yields
Goodbye
The above shows how new methods can be attached to a class without funcToMethod
or transplant
. Both funcToMethod
and transplant
try to attach functions to instances of the class rather than the class itself. This is wrong-headed, which is why it requires contortions (like having to pass jimmy
as an argument in jimmy.say2(jimmy, 'Good Bye!')
) to make it work. Methods should be defined on the class (e.g. Patient
), not on the instance (e.g. jimmy
).
transplant
is particularly horrible. It uses a class when a function would suffice. It uses the archaic apply
instead of the modern self.method(*nargs, **kwargs)
syntax, and ignores the PEP8 convention for camelCasing class names. In its defense, it was written over ten years ago. But fundamentally, what makes it an anathema to good programming is that you just don't need it.
All you need to do is wrap the function in a staticmethod()
call:
say = staticmethod(say)
or apply it as a decorator to the function definition:
@staticmethod
def say(host, msg):
# ...
which comes down to the same thing.
Just remember; the @decorator
syntax is just syntactic sugar for writing target = decorator(target)
, where target
is the decorated object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With