@VTR

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

for文のアンダーバー_の意味について

Udemyのkaggleの講座にて、Pythonをコードで以下のコードが出てきました。

for _, (ids_train, ids_valid) in enumerate(skf.split(x_train, t)):
x_tr = x_train.loc[ids_train, :]
x_val = x_train.loc[ids_valid, :]
t_tr = t[ids_train]
t_val = t[ids_valid]

上記のfor文の_,の意味が分からず、下のサイトで_について勉強したのですが、

やはりその上でもなぜ_があるのかがよく分かりません・・。
教えていただけないでしょうか?

0 likes

4Answer

アンダースコアで表される仮変数はC#風に言うと 破棄(Discards) といいますが,これは絶対に使わない(使えない)変数になります.主目的は可読性と保守性の向上です.

複値返却ライクな書き方ができる言語において特に有用ですが,型制約上書かないといけないけどスコープ内で使わないという場合などに使用すると,1文字の変数が散らかって読みづらくなったり,意図せず変数が衝突したりするのを防ぎます.

ざっくり言うとこういう時のための機能だと思ってください:

for i in range(5):
  for j in range(7):
    # Needless 2 variables for just looping
    print("Just prints messages without any variables")

    # Needless value conflicts loop counter
    (i, name) = someReturnsMultiValue()
    print(f"Her name is {name}")

for _ in range(5):
  for _ in range(7):
    # Prevents variables remain on scope
    print("Just prints messages without any variables")

    (_, name) = someReturnsMultiValue()
    print(f"Her name is {name}")
2Like

Comments

  1. @VTR

    Questioner

    ありがとうございます。まだかなりの初心者なのでせっかく作ってくれたコードをまだ理解できていませんが、なんとなく「そんな重要な変数じゃないけど、もし今後重要になる変数と被ったら嫌だから、使い捨てる変数が欲しい」というときに使うのかなと理解しました。私が投稿したコードでいうと「ids_train, ids_validを何かの変数に入れたいが、使い捨てるくらいでいいから_(アンダーバー)を使おう」ということですかね。

  2. 私が投稿したコードでいうと「ids_train, ids_validを何かの変数に入れたいが、使い捨てるくらいでいいから_(アンダーバー)を使おう」ということですかね。

    いまいちご理解されていないようなので補足しますがenumerateはリストのインデックスと要素を各々タプルで返却します.本来受け取るべき_にインデックスが,(ids_train, ids_valid)に要素が入っています. そのうちインデックスは使わないので破棄しています.

    破棄に使われるのは単独のアンダースコアで表される変数のみで,その他は全く関係ありません.

  3. @VTR

    Questioner

    ありがとうございます!そういう使いかたもできるんですね。enumerateはインデックスと要素をセットで返すが、インデックスのみいらないため、インデックスに当てはまる変数を使い捨てる_にしている、ということでしょうか。
    難しいですね^^;

余談ですが、元のコードは enumerate() でインデックスを付与してそれを捨てるという無駄なことをしていますね。無駄を省けば以下のように書けます。

for ids_train, ids_valid in skf.split(x_train, t):
    x_tr = x_train.loc[ids_train, :]
    
2Like

Comments

  1. 他の回答への対応をみると違うようですが、僕は質問者さんはそこを聞いているのだと思ってました。
    質問にあるコードは、わざわざデータに連番(インデックス)を付けるような処理をしているのに、その連番が不要だから捨てているというなんとも不可解なコードになっています。なので、そこが疑問なのであれば、気にする必要は無いと思います。
    理由があるとすれば、当初は連番を必要としていたが、修正しているうちに不要になったとか、作った人にenumerateを付ける癖があるとかでしょうか。

for文に限りませんが、関数の戻り値が複数ある場合に不要な戻り値があるときに変数名としてアンダーバーが使用されます。関数が複数の値を戻り値として返すので受け取る必要がありますが、その後のプログラムで使用しない場合にそれを明示するためにアンダーバーを使用します。

1Like

単独の_はその値を使わない事を意味します
変数のゴミ箱と思えばいいです
pythonでは次のようなことができますが、_を使うというのはゴミ箱を漁るようなものなので基本NGです

_ = 10
print(_)  # 出力: 10
1Like

Your answer might help someone💌