2017-02-14 8 views
0

以下の例では、ReturnValueクラスのすべての'resolve'メソッドを明示的に定義する必要があります。Pythonで特に名前が付けられた動的クラスメソッド

ループ内でこれらのメソッドを自動的に定義できれば、同じことをやっているだけで、クラスメンバ変数の名前と一致するメソッドの名前が違います返されます。

これはPython 2.7で可能ですか?それはあまりにも多くの行を保存していない、

class ReturnValue(graphene.ObjectType): 
    class Meta: 
     interfaces = (ReturnKeys,) 


def set_resolve_method(animal): 
    setattr(
     ReturnValue, 
     'resolve_' + animal, 
     lambda self: getattr(self, animal) 
    ) 

for animal in ('dog', 'cat', 'horse', 'bear'): 
    # this function scoped the variable `animal` 
    set_resolve_method(animal) 

をしかし、あなたは以下を参照してください。

import graphene 


class ApiObj(object): 
    @staticmethod 
    def get_values_as_dictionary(): 
     return {'dog': 'pound', 'cat': 'nip', 'horse': 'fly', 'bear': 'down'} 


class ReturnKeys(graphene.Interface): 
    dog = graphene.String() 
    cat = graphene.String() 
    horse = graphene.String() 
    bear = graphene.String() 


class ReturnValue(graphene.ObjectType): 
    class Meta: 
     interfaces = (ReturnKeys,) 

    def resolve_dog(self): 
     return self.dog 

    def resolve_cat(self): 
     return self.cat 

    def resolve_horse(self): 
     return self.horse 

    def resolve_bear(self): 
     return self.bear 


api = ApiObj() 
value_dict = api.get_values_as_dictionary() 
rv = ReturnValue(**value_dict) 

print rv.resolve_cat() 
print rv.resolve_dog() 
print rv.resolve_horse() 
print rv.resolve_bear() 

答えて

2

組み込み__getattribute__とリターンを使用してメソッド呼び出しをインターセプトすることです「解決」メソッドが受信されたときの特定の属性

このコードは、ジョブを実行する必要があります。

class ReturnValue(graphene.ObjectType): 
    class Meta: 
     interfaces = (ReturnKeys,) 

    def __getattribute__(self, attr): 
     if attr.startswith("resolve_"): 
      return lambda: getattr(self, attr[8:]) 
     return super().__getattribute__(attr) 

@Philip Tzouの答えとの差がsetattrがするように、ここで私たちは、クラス内のすべてのメソッドを追加していないことです。その代わりに、要求に応じて属性を直接返します。あなたの使用の場合に応じて、これは良いかもしれないし、そうでないかもしれません。このため

return lambda: getattr(self, attr[8:]) 

return lambda: self.common_function(attr[8:]) 

フィリップが彼の答えの最後に言及して何も

は、この行を置き換える場合は検討すると、上記のコードで実施することができることが重要ですこのコードはPython 3で書かれているので、Python 2で動作させるためにはsuper()の構文を変更する必要があります。

+0

ありがとう@martin、私はあなたの解決策をPython2で動かすことができました。影響を受けたクラスの中にすべてがカプセル化されていることに感謝します。デバッガを介して実行を追跡しようとすると、私はもっと混乱してしまいます...しかし、それは動作します! – Swoop

+0

Btwの場合、 'resolve_xxx'は' Interface'のサブクラスでも実装できます。たぶんあなたの場合、 'ReturnValue'でそれらを持つ必要はありません。 –

1

私は、これは動作するはずだと思います。そして、私は、すべてのメソッドを明示的に定義することは、実際にはより良いpythonの方法だと思います。あなただけの各方法のうち、共通部分を分離し、いくつかの複雑なコードを再利用し、このような機能分離に入れしようとしている場合は、次の代替を

def common_function(animal): 
    pass # do something here 


class ReturnValue(graphene.ObjectType): 
    class Meta: 
     interfaces = (ReturnKeys,) 

    def resolve_dog(self): 
     return common_function(self.dog) 

    def resolve_cat(self): 
     return common_function(self.cat) 

    ... 
+0

ありがとうございます@philip。実際の実装では、大規模な辞書を返すAPIエンドポイントを照会するときにこれを使用します。 '' resolve_''メソッドのそれぞれは単にそのキーの値を返しますので、私は多くのコード行を保存しています...私は確信していますが、魔法を記述するために必要なコメントを追加することになります – Swoop

関連する問題