2012-09-19 12 views
5

私が使用しているオープンソースパッケージのソースコードを見てきました。ほぼすべての関数は、名前付き引数の代わりに* argsを使用します。関数を呼び出すたびに、私は元に戻って、ソースコードを選択し、引数が何でなければならないのか、そしてどのような順序であるべきかを特定する必要があるため、コードをフォローして使用するのが難しいと思っています。私が持っている質問は、すべての関数で* argsを使用する魅力的な理由があるのでしょうか?これは概念の乱用ですか?それは(引数の数が間違って関数を呼び出す)あなたのコード内のエラーをマスクすることができますので、すべての機能に*argsを使用して おかげで、 -bPythonでの* argsの適切な使用と比較

+0

* argsがある場合は、(正確な!)ドキュメントストリングが必要です。 – James

+0

どのパッケージですか?非難ゲームをするのではなく、正当な理由があるかもしれません。 –

答えて

4

これは個人的な推論かもしれませんが、いくつかのフィールドが特定のコンテキストでのみ使用される多くのオプションフィールドがある場合は、* argsと** kwargsを使用します。

私がargsを使用した唯一の唯一のケースは、クラウドAPI用のXML RPCクライアントを構築していたときです。私は基本的なレイヤーにパラメータを渡していたので、動的に生成された関数のために他の選択肢はありませんでしたが、* argsはすべてのパラメータを事前に知る方法がないため使用できませんでした。

ほとんどの場合、あなたはそれを必要としません。私はそれが何よりも怠け者だと考えています。

JavaとC#から来ている人が、これを "params"の代わりに使うかもしれませんが、pythonでオプションのパラメータを渡す方法はたくさんあります。

また、* argsを使用しても、非常に良い文書があるはずです。

+0

2年のコーディングの中で、私は 'params'を2回使用しました。 Pythonの1ヶ月で、私は '(* args、** kwargs)'を何度も見て、それが私の目を傷つけさせた。私はそれを控えめに使用することをお勧めします。それは非常に特定の問題を解決するために使用すべきツールです。われわれが知っているように、使いやすいツールを人に与えると、そのツールを使いすぎて悪用することになります。 – Dagrooms

3

は悪い考えです。 が必要な場合は、*args*argsが必要です。

2

*argsを使用する魅力的な理由がない場合、それは概念の悪用です。通常、議論のための良い名前があり、それは理解に役立ちます。存在しない場合でも、(x, y, z)(*args)以上を通知します。

さらにコードを読みやすくすることは、エラーを捕捉するのにも役立ちます(たとえば、(2, 3)(x, y, z)関数を呼び出すと、関数の内部ではなくエラーが発生します)、通常はより簡潔ですそれはより効率的でもあります。

しかし、時には*argsが広く使用される魅力的な理由があります。

たとえば、低レベル(Cまたはその他の)モジュールをラップしていて、完璧な転送をしたい場合は、*argsで簡単です。ラッパーコードを手動で記述するのではなく、自動的に生成する場合はさらにそうです。もちろん、これはまだトレードオフです。ラッパーモジュールの開発者にとってははるかに簡単ですが、ユーザーにとっては難しくなりますが、トレードオフが必要な場合もあります。

あなたが参照している特定のパッケージを知らないと、それが魅力的な使用例か濫用かを推測することは不可能です。

3

Zen of Pythonでは、明示的に暗黙的に指定することを推奨しています。可能であれば、明示的な引数を使用する必要があります。

+1

+1、禅からの引用。 – nneonneo

+1

@nneonneoさらなるコメントなしで禅から引用するのはかなり役に立たない。 Zen of Pythonのガイドラインは素晴らしいですが、PythonのZenにあるだけでなく、*良い理由*のための良いアイデアです。 Pythonの禅を覚えておかないと*それらのガイドラインの理由を理解することはできません。 – Ben

+0

@ベン、私はそれがなぜその特定のアイテムが禅にあるのか推測する私の場所だとは思わなかった。この場合、私はそれがかなり明白だと思いました - 明示的に理解し、従うのは簡単です。また、プラットフォーム設計者を導くのと同じ原則で作業するだけで、Pythonだけでなく、全体的に物事を全体的に良くすることが分かりました。 –

2

未知の関数をラップする場合(デコレータによって返される関数はこれを行うことが多い)、しばしば(*args, **kwargs)を使用する必要があります。

一部のクラス階層では、階層内の異なるクラスで異なる署名が必要なメソッドで(*args, **kwargs)を使用しています(__init__が主な原因です)。 は本当にですが、これを避けることができますが、複数の継承階層を正常な方法で(または複数の継承で可能な限り)使用する必要がある場合に役立ちます。

多くのオプションの引数がある場合、時々**kwargsを使用することになりますが、これには多くのドキュメントが必要です。 (デコレータやクラスの継承例のように、未知の署名と他のいくつかの関数に渡すのではなく)*argsそのものを消費しています機能で

、私は*argsをする以外には使用しないことがほとんどないべきであると考える傾向があります同じ種類のものが0個以上あることを意味します。その場合は*websitesまたは*spaceshipsまたは*watermelonsとし、*argsではなく名前を付ける必要があります。無関係なパラメータの束は、*argsに押しつぶされるべきではありません。さらに悪いことに、関数 "x、y、a、z、あるいはxとz"を取る関数は*argsです。ここで、2番目のパラメータは渡されるパラメータの数に応じて異なることがあります。その時点で、彼らは明らかに名前とデフォルトを持っていなければなりません(たとえそれが標準であったとしても、Noneのデフォルトでは、機能の中ではNoneパターンではありません)、位置ではなくキーワードで渡されます。

関連する問題