2011-10-28 13 views
3

私は現在、PythonでAPIライブラリを書いているし、次のコードがあまりにもunpythonicある場合、私は思ったんだけど:繰り返しコードを防ぐために、** kwargsとデコレータを使用することは許されますか?

@accepts('video_id', 'reference_id', 'page_size', 'page_number', 
     'get_item_count', 'fields', 'video_fields', 'custom_fields', 
     'media_delivery', 'output') 
@requires('video_id', 'reference_id') 
def find_related_videos(self, **params): 
    return ItemCollection(read_request(params)) 

リスト内の任意kwargsからではないが渡された場合acceptsデコレータはエラーをスローします方法。また、特定のキーワードの検証も行います。

requiresデコレータは、それらのキーワード引数が存在することを保証します。

メソッド定義にキーワードargsがないと私に迷惑がかかります。しかし、各メソッドに対して手動でparams辞書を構築する必要もあり、迷惑に見えます。また、メソッドに渡される引数のvideo_fieldsのインスタンスごとに同じ検証コードがあります。したがって、自分自身を繰り返さないようにacceptsデコレータから呼び出すことができます。

思考?

答えて

1

私は間違いなく、メソッドのシグネチャで必要なフィールドを置くところ:

def find_related_videos(self, video_id, reference_id, **params): 
    params.update({'video_id': video_id, 'reference_id': reference_id}) 
    return ItemCollection(read_request(params)) 

可能ならば、私も同様にキーワード引数を取るようにread_requestを変更したい:

def find_related_videos(self, video_id, reference_id, **params): 
    return ItemCollection(read_request(video_id=video_id, reference_id=reference_id, **params)) 

限り受け入れ可能なパラメータは個人的には無効なパラメータのためにエラーを投げることはありません。私は必要のないパラメータを無視します。

+1

私はここにいくつかの味があることを知っていますが、呼び出し側が変数を渡している場合、呼び出し側はその変数が重要であると予想しており、呼び出し側はそれを無視することは予想外です。これは予期せぬ結果につながる可能性があり、それは良いことではありません。私は一般的に、エラーを投げて、プログラマーにパラメータを無視してプログラマーを驚かせるよりも重要なことを見てもらう方が良いと思います。 – TimothyAWiseman

0

私はデコレータなしでそれを行います。はるかに簡単に装飾することなく、コードのexecutationパスを追跡する読者のために:

required = set(['video_id', 'reference_id']) 
acceptable = required.union(set(['page_size', 'page_number', 'get_item_count', 'fields', 'video_fields', 'custom_fields', 'media_delivery', 'output'])) 

def find_related_videos(self, **params): 
    if not (required.issubset(set(params.keys())) or set(params.keys()).issubset(acceptable)): 
     raise Exception("Some exception") 
    return ItemCollection(read_request(params)) 

これは、すべてのkwargsからキーがacceptableセットであり、少なくともrequired引数を持っているかどうかをチェックします。

1

このソリューションについてはどうですか?

​​

これはcheck_params()にカスタムテストをfacitlitatingながら、Pythonのに許容可能であり、必要なパラメータのチェックを残します。

0

あなたがこれを行うにした場合:

def find_related_videos(self, video_id, reference_id, ...) 

が、あなたはまだ引数の有効性を確認するためにデコレータを使用して、あなたのための残りを強制するために通訳を残すことができます。しかし、いくつかのトレードオフがあります。

  • ポジション引数を使用すると、呼び出し元は任意の順序で引数を指定できなくなります。あなたが基本的に辞書を読んでそれを渡すなど、これは問題になる可能性があります。
  • @accepts(または@validate)デコレータを書いて、同じ一般的な方法で引数の妥当性をチェックするのは難しいです。それはまだinspect.getargspec関数を使って行うことができます。私はこれまでと同じようなことをやったことがありますが、動作させるには時間がかかります。私のデコレータは、HTTP GETパラメータと関数引数を自動的に照合するのは複雑ですが、動作します。
関連する問題