web-dev-qa-db-ja.com

Python:引数が多すぎることに関するパイリント警告を回避する

大きなPython関数を小さな関数にリファクタリングします。たとえば、次のコードスニペットを考えます。

x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9

もちろん、これは些細な例です。実際には、コードはより複雑です。私のポイントは、抽出された関数に渡す必要のある多くのローカルスコープ変数が含まれていることです。

def mysum(x1, x2, x3, x4, x5, x6, x7, x8, x9):
    x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
    return x

問題は、pylintが引数が多すぎるという警告をトリガーすることです。次のようなことを行うことで、警告を回避できます。

def mysum(d):
    x1 = d['x1']
    x2 = d['x2']
    ...
    x9 = d['x9']
    x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
    return x

def mybigfunction():
    ...
    d = {}
    d['x1'] = x1
    ...
    d['x9'] = x9
    x = mysum(d)

しかし、このアプローチは見苦しいため、冗長なコードを大量に書く必要があります。

それを行うためのより良い方法はありますか?

40
Anonymous

まず、 Perlisのエピグラム のいずれか:

「10個のパラメータを持つプロシージャがある場合、おそらくいくつかを見落としていました。」

10個の引数のいくつかはおそらく関連しています。それらをオブジェクトにグループ化し、代わりに渡します。

質問に直接答えるのに十分な情報がないため、例を作ります:

class PersonInfo(object):
  def __init__(self, name, age, iq):
    self.name = name
    self.age = age
    self.iq = iq

次に、10個の引数関数:

def f(x1, x2, name, x3, iq, x4, age, x5, x6, x7):
  ...

になる:

def f(personinfo, x1, x2, x3, x4, x5, x6, x7):
  ...

呼び出し元は次のように変わります。

personinfo = PersonInfo(name, age, iq)
result = f(personinfo, x1, x2, x3, x4, x5, x6, x7)
89
user97370

引数を渡すより良い方法が必要ですか、それともpylintが苦労するのを止める方法が必要ですか?後者の場合、次の行に沿ってコードにpylint- controllingコメントを挿入することで、しつこいを止めることができたことを思い出すようです。

#pylint: disable-msg=R0913

または:

#pylint: disable-msg=too-many-arguments

できるだけ早くそれらをオンにすることを忘れないでください。

私の意見では、何もありません本質的に多くの引数を渡すことに誤りがあり、いくつかのコンテナ引数でそれらをすべて包み込むことを提唱するソリューションは、pylintを停止する以外、実際には問題を解決しませんしつこい:-)。

20個の引数を渡す必要がある場合は、それらを渡します。関数が多すぎてリファクタリングがそこで役立つ可能性があるため、これが必要になる可能性があります。これはあなたが見るべきものです。しかし、それは決定ではありません我々は、「本当の」コードが何であるかを見ない限り、本当にすることができます。

38
paxdiablo

Pylintの引数の最大許容数を簡単に変更できます。 pylintrcファイルを開いて(まだ持っていない場合は生成して)、変更します。

max-args = 5

に:

max-args = 6#またはあなたに合った値

Pylintの manual から

セットアップとコーディング標準に適したすべてのオプションを指定するのは面倒なので、rcファイルを使用してデフォルト値を指定することができます。 Pylintは/ etc/pylintrcおよび〜/ .pylintrcを探します。 --generate-rcfileオプションは、標準出力の現在の構成に従ってコメント化された構成ファイルを生成し、終了します。このオプションの前に他のオプションを配置して構成で使用したり、デフォルト値から始めて構成を手動で調整したりできます。

22
Nadia Alramli

Pythonの変数引数 機能を使用してみてください:

def myfunction(*args):
    for x in args:
        # Do stuff with specific argument here
12
hbw

おそらく、引数の一部をメンバー変数に変えることができます。そのような状態が必要な場合、クラスは私にとって良いアイデアのように聞こえます。

7
Brian Rasmussen

関数を単純化または分割して、9つの引数を必要としないようにします(または、パイリントを無視しますが、リントツールの目的に反する提案のように回避します)。

編集:それが一時的な措置である場合、ここで説明されているようにコメントを使用して、問題の特定の機能の警告を無効にします: http://lists.logilab.org/pipermail/python-projects/2006-April/000664。 html

後で、無効になっているすべての警告をgrepできます。

6
Dave

私は番号を参照するのが好きではありません。記号名ははるかに表現力があり、時間の経過とともに陳腐化する可能性のあるコメントを追加する必要がありません。

だから私はむしろしたい:

#pylint: disable-msg=too-many-arguments

また、ぶら下げたままにしないことをお勧めします。ファイルが終了するか、無効になるまで、アクティブになります。

とても良いこと:

#pylint: disable-msg=too-many-arguments
code_which_would_trigger_the_msg
#pylint: enable-msg=too-many-arguments    

また、1行につき1つの警告/エラーを有効/無効にすることをお勧めします。

4
Igor Stoppa

私は同じ厄介なエラーに遭遇しましたが、PyCharmが自動的に検出するクールな機能と関係があることに気付きました... @staticmethodデコレータを追加するだけで、メソッドが使用されている場所でそのエラーが自動的に削除されます

0
Ants

Pythonには、ニーズに合ったニースの関数型プログラミングツールがいくつかあります。 lambda functions および map を確認してください。また、リストを使用したほうがはるかに適切だと思われる場合は、辞書を使用しています。提供した簡単な例については、このイディオムを試してください。マップはより良く、より速くなりますが、あなたのニーズに合わないかもしれないことに注意してください:

def mysum(d):
   s = 0  
   for x in d:
        s += x
   return s

def mybigfunction():
   d = (x1, x2, x3, x4, x5, x6, x7, x8, x9)
   return mysum(d)

たくさんのローカル変数を持っていると述べましたが、率直に言って、リスト(またはタプル)を扱っている場合は、リストを使用して、長期的にすべてのローカル変数を除外する必要があります。

0
easel