2017-08-11 12 views
1

クラスメソッドを使用する場合、サブクラスのメソッドを動的に変更するには、メソッドのシグネチャを動的に変更するにはどうすればよいですか?サブクラスでメソッドのシグネチャを動的に変更するにはどうすればよいですか?

import inspect 

class ModelBase(object): 

    @classmethod 
    def method_one(cls, *args): 
     raise NotImplementedError 

    @classmethod 
    def method_two(cls, *args): 
     return cls.method_one(*args) + 1 

class SubClass(ModelBase): 
    @staticmethod 
    def method_one(a, b): 
     return a + b 

test = SubClass() 

try: 
    print(inspect.signature(test.method_two)) 
except AttributeError: 
    print(inspect.getargspec(test.method_two).args) 

私はtest.method_twotest.method_oneの署名を取得したいです。親クラスModelBaseを書き換える方法は?

私は約Preserving signatures of decorated functionsを読んでいます。 python3.4 +では、functools.wrapsは装飾された関数の署名を保持するのに役立ちます。私はそれをクラスメソッドに適用したい。

functools.wrapsを使用する場合、装飾されたメソッドの名前を割り当てる必要があります。しかし、この状況でclassmethod以外の装飾されたメソッドにアクセスする方法はありますか?

from functools import wraps 

class ModelBase(object): 

    @classmethod 
    def method_one(cls, *args): 
     raise NotImplementedError 

    @classmethod 
    def method_two(cls): 
     @wraps(cls.method_one) 
     def fun(*args): 
      return cls.method_one(*args) + 1 
     return fun 

method_two包まれた関数を返しますが、私はtest.method_two()(*arg)でそれを使用する必要があります。この方法は直接ではありません。これは、イントロスペクションの目的のためだけであれば

答えて

1

あなたは私たちがmethod_oneのシグネチャを持つ関数を返すアクセスされModelBaseたびmethod_two__getattribute__をオーバーライドすることができます。

import inspect 

def copy_signature(frm, to): 
    def wrapper(*args, **kwargs): 
     return to(*args, **kwargs) 
    wrapper.__signature__ = inspect.signature(frm) 
    return wrapper 


class ModelBase(object): 

    @classmethod 
    def method_one(cls, *args): 
     raise NotImplementedError 

    @classmethod 
    def method_two(cls, *args): 
     return cls.method_one(*args) + 1 

    def __getattribute__(self, attr): 
     value = object.__getattribute__(self, attr) 
     if attr == 'method_two': 
      value = copy_signature(frm=self.method_one, to=value) 
     return value 


class SubClass(ModelBase): 
    @staticmethod 
    def method_one(a, b): 
     return a + b 


class SubClass2(ModelBase): 
    @staticmethod 
    def method_one(a, b, c, *arg): 
     return a + b 

デモ:

>>> test1 = SubClass() 
>>> print(inspect.signature(test1.method_two)) 
(a, b) 
>>> test2 = SubClass2() 
>>> print(inspect.signature(test2.method_two)) 
(a, b, c, *arg) 
+0

ありがとうございます!これはCodeGenのためのものです。 method_twoのcodegenを実行するには、method_oneの署名が必要です。 – Ryan

関連する問題