I found非常好的例子如何动态地向类中添加新方法(移植类):
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!')
但我不明白,如何修改它以添加静态方法。有人能帮助我吗?
答案 0 :(得分:18)
您需要做的就是将函数包装在staticmethod()
调用中:
say = staticmethod(say)
或将其作为装饰器应用于函数定义:
@staticmethod
def say(host, msg):
# ...
归结为同样的事情。
记住; @decorator
语法只是写target = decorator(target)
的语法糖,其中target
是装饰对象。
答案 1 :(得分:5)
我在这里看不到静态方法。 say
函数需要两个参数,第一个参数host
似乎是该类的实例。
所以看起来你只是想把一个新方法附加到一个类。这可以在没有funcToMethod或移植的情况下完成:
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')
产量
Jimmy says Hello
如果您确实要附加静态方法,那么,正如MartijnPieters所回答的那样,使用staticmethod
装饰器:
def tell(msg):
print(msg)
if __name__ == '__main__':
jimmy = Patient('Jimmy')
Patient.tell = staticmethod(tell)
jimmy.tell('Goodbye')
产量
Goodbye
以上显示了如何将新方法附加到没有funcToMethod
或transplant
的班级。 funcToMethod
和transplant
都尝试将函数附加到类的实例而不是类本身。这是错误的,这就是为什么它需要扭曲(比如必须在jimmy
中传递jimmy.say2(jimmy, 'Good Bye!')
作为参数)才能使它工作。应该在类(例如Patient
)上定义方法,而不是在实例上定义(例如jimmy
)。
transplant
特别可怕。当函数足够时它使用一个类。它使用古老的apply
而不是现代self.method(*nargs, **kwargs)
语法,并忽略了camelCasing类名的PEP8约定。在它的辩护中,它是十多年前写的。但从根本上说,让它成为良好编程的诅咒的原因在于你只是不需要它。
答案 2 :(得分:0)
以下是有效的方法,即在患者身上采用静态方法,我认为OP需要这样做。
def tell(msg):
print(msg)
...
funcToMethod(tell, Patient, 'say3')
...
Patient.say3('Bye!')