Python関数呼び出しで未使用の戻りパラメーターに使用するスタイル


30

関数が値のタプルを返すが、それらの値の1つだけが後で使用される状況を処理するための推奨/一般的に受け入れられているコーディングスタイルはありますか呼び出しはおそらく少しやり過ぎです...)?する代わりに

a, b, c = foo()

そして、andを使用bしないだけcで、次のバリアントのうちどれを優先する必要がありますか(または別のものがありますか?):

バリアント1(アンダースコア)

a, _, _ = foo()

(これは非常に明確でシンプル_ = gettext.gettextですが、翻訳を使用する多くのアプリケーションでの使用と衝突する可能性があります)

バリアント2(ダミー名)

a, unused, unused = foo()

(あまり魅力的ではない、私は思う、同じような他の名前にも当てはまりますdummy

バリアント3(インデックス)

a = foo()[0]

(私にとっては、()[0]Pythonに見えない…)


私の以前の答えとは対照的に、戻り値の2/3を参照したい場合、バリアント3ではどうなりますか?Pythonを正当化するのに十分な知識がないことに気付いたので、答えを削除しました。
クレイジュ

@クレイジ:あなたがそれを削除する前にあなたの答えを見ませんでした...あなたはうまくいくかどうか尋ねていますかa, b = foo()[0:2]?はいの場合:はい、そうです:)
user49643

それはまさに私が求めていたものでした。それが機能する場合(あなたが言ったように)バリアント3を使用します。この情報が与えられれば、答えを復元します。
クレイジュ

3
なお、これらの日は、あなたがのために、むしろ美しい構文を使用することができ開梱「拡張」をa, *_ = foo()最初の1以外のすべての値を捨てます。
ベンジャミン・ホジソン

回答:


17

未使用の変数にアンダースコアを使用することは間違いなく受け入れられます。ただし、一部のコードベースでは、その識別子はの省略形として予約されているため、オプションではありませんgettext。これは、このスタイルに対する最も頻繁な異議です(ただし、私が判断できる限り、それは大多数の問題ではありません)。私はまだそれをお勧めし、常に自分で使用します。

以下のような名前dummyかは、unused個人的に私を刺激する傾向がある、と私はひどく頻繁にそれらが表示されない(つまり、Pythonで-私が使用してDelphiのコードベースを知っているdummy自由を、そしてそれはまた、問題のプログラムに関連付けられたスクリプトに漏れました)。それに反対するアドバイスをします。

返されたタプルから1つのアイテムを抽出するだけでも大丈夫です。また、未使用の値の数を適切に取得する手間が省けます。ただし、2つの潜在的な欠点があることに注意してください。

  • 値の数が予想と異なる場合、爆発しません。これ、混同やタイプミスを検出するのに役立ちます。
  • 戻り値がシーケンスである場合にのみ機能します(ほとんどがタプルとリストですが、一般的なままにします)。率直に言って、コード内の1つのクラス(2Dベクトル)は反復可能で、一定数の値を生成します(したがって、割り当てのアンパックに使用できます)が、インデックス化できません。

実際に質問でgettextに言及しました:)とにかく、私はあなたの答えを受け入れました-明確な単一の受け入れられたスタイルはないようですが、あなたの答えはいくつかの興味深いポイントを上げました。
user49643

gettextの問題を回避する(またはインタープリターでの同様の問題を回避する)には、単一の代わりに二重下線(別名dunders)を使用できます。
Zim

21

Pylintは、このようにする習慣を身につけました。

widget, _parent, _children = f()

つまり、未使用の結果には、接頭辞として_が付いたわかりやすい名前が付けられます。Pylintは、_で始まるローカルを未使用と見なし、_で始まるグローバルまたは属性をプライベートと見なします。


3

プロジェクト全体で、これを1回だけ実行する場合、または特定の関数について非常にまれにしか実行しない場合、ご存じの場合はバリアント1を使用します gettextない、そのモジュールで問題がないいる、それ以外の場合はVariant 3を使用します。

一方、これを頻繁に行っていた場合、特に戻り値の異なるサブセットが必要な場合(ラッパーを作成して、関心のあるものだけを返します)、ラッパーを書くことは有益かもしれません結果を名前付きtuple、または他の記述クラスのインスタンスに配置します。

bar = foo()

そしてと協力bar.abar.bそしてbar.c


2

他の人が言ったように、アンダースコア(_)が標準です。しかし、下線が翻訳に使用されている場合、二重下線が最良の選択肢だと思います。

var, __, value = "VAR=value".partition('=')

これらよりも良い:

var, unused, value = "VAR=value".partition('=')

var, unused_del, value = "VAR=value".partition('=')

var, _del, value = "VAR=value".partition('=')


1

私はPython以外のプログラマーですが、私にとっては3番目のバリアントが最も理にかなっています。

バリアント3では、どの値に対処することに関心があるのか​​が明確にわかります。バリアント1および2では、値を変数に割り当て直すため、それらを使用できます。あいまいな名前を付けたかもしれませんが、不適切な名前付けは実際には問題の解決策ではありません。

明確さは別として、メモリ内のスロットに未使用の値を割り当てる必要があるのはなぜですか(バリアント1および2)。これは、メモリ管理の点で不十分なソリューションになります。


常に同じ変数に配置すると、メモリの問題は常に1つの変数のサイズだけになりませんか?それが問題になるとは思わない。
マイケルマッケイド

-2

一般的なルールは次のとおりです。戻り値の1つのみを使用する場合、単純にその1つの値を返しませんか?フラグが複数の場所から呼び出されている場合、同じフラグを保持し、フラグごとに値を返します。

編集:

私があなたの状況にあり、関数を書いていなかった場合、おそらくVariant 2に行きます。必要に応じてパラメーターを使用できるように、ダミーの名前をそこに残しておきます。リストのスライスには少しオーバーヘッドがあります。おそらく、不要なデータを受信するために数バイトを節約できます。


-1彼は関数を定義しなかったので、返されるものを変更できないと推測しています。私は彼が関数が3つの値を返すときに言及していると思いますが、彼は現在のユースケースで1つしか気にしません。
クレイジュ

@Craige:はい、私は変更できない機能を意味しました-それを明確にする質問にメモを追加しました。
user49643

オーバーヘッドは確かですか?非常に簡単なipythonテストを試しました:%timeit a, _, _ = foo()vs %timeit a = foo()[0]. 123ns対109nsになりました。つまり、スライスは実際に値を展開するよりも速いようです。または、特定の状況を念頭に置いていましたか?
user49643

2
もう1つのもっともらしいシナリオは、一部の呼び出しにすべての値が必要なわけではないということです。
キーストンプソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.