11

发现了非常好的例子,如何动态地向类添加新方法(移植类):

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!')

但我不明白,如何修改它以添加静态方法。有人能帮我吗?

4

3 回答 3

23

您需要做的就是将函数包装在一个staticmethod()调用中:

say = staticmethod(say)

或将其作为装饰器应用于函数定义:

@staticmethod
def say(host, msg):
    # ...

这归结为同一件事。

只要记住; @decorator语法只是写作的语法糖,装饰对象target = decorator(target)在哪里。target

于 2013-02-01T11:33:17.787 回答
6

我在这里看不到静态方法。该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

上面显示了如何将新方法附加到没有funcToMethodor的类transplant。两者都funcToMethod尝试transplant将函数附加到类的实例而不是类本身。这是错误的,这就是为什么它需要扭曲(例如必须jimmy作为参数传递 in jimmy.say2(jimmy, 'Good Bye!'))才能使其工作。方法应该定义在类上(例如Patient),而不是实例上(例如jimmy)。

transplant特别可怕。当函数足够时,它会使用一个类。它使用古老的apply而不是现代的self.method(*nargs, **kwargs)语法,并且忽略了 PEP8 对 camelCasing 类名的约定。为其辩护,它是十年前写的。但从根本上说,让优秀编程成为一种诅咒的是你根本不需要它。

于 2013-02-01T11:41:47.460 回答
0

那么下面的作品,即在我认为OP想要的Patient上放置一个静态方法。

def tell(msg):
   print(msg)

...

funcToMethod(tell, Patient, 'say3')

...

Patient.say3('Bye!')
于 2013-02-01T11:52:13.637 回答