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

ここには staticmethod がありません。関数は 2 つの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

staticmethod をアタッチしたい場合は、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に関数をアタッチしようとします。これは頭​​がおかしいため、機能させるにはゆがみ (で引数として渡さなければならないなど) が必要です。メソッドは、インスタンス (例 ) ではなく、クラス (例 ) で定義する必要があります。jimmyjimmy.say2(jimmy, 'Good Bye!')Patientjimmy

transplantは特にひどいです。関数で十分な場合は、クラスを使用します。apply最新の構文ではなく古風な構文を使用self.method(*nargs, **kwargs)し、キャメルケース クラス名の PEP8 規則を無視します。その弁護において、それは10年以上前に書かれました. しかし、基本的に、それが優れたプログラミングにとって忌み嫌われるのは、それが必要ないということです。

于 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 に答える