質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.81%

for文の因果関係について

受付中

回答 8

投稿

  • 評価
  • クリップ 0
  • VIEW 625

okahijiki

score 226

基本的な質問にて失礼します。

以下のfor文ですが、1回目のループでnに入ったtaroが出力され、同様に2回めのループではjiro、3回めではsaburo、4回目ではshiroが出力されるのは直感的に、なにも違和感がありません。

for n in ['taro','jiro','saburo','shiro']:
    print(n)

taro
jiro
saburo
shiro

しかし、たとえば、以下のようにHelloが4回出力されるケースについて、素直になれないのです。たしかに、inのリストの数が4つ、なのでhelloも4つなのですが..もう少し、突っ込んだ因果関係を知りたいと思ったりしています。どうぞ、よろしくお願いいたします。

for n in ['taro','jiro','saburo','shiro']:
    print('Hello')

hello
hello
hello
hello
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ozwk

    2020/07/20 10:45

    疑問は
    Helloが4回出力される処理の仕組みですか?
    それとも「ループ内で列挙したもの(n)を使わなくてもエラーにならない」という言語仕様を定めた理由ですか?

    キャンセル

  • okahijiki

    2020/07/20 10:50

    たぶん、両方ですー。

    キャンセル

  • nto

    2020/07/20 15:45 編集

    ご自身の中で「値を必ず使用しなければならない」と潜在的に既成概念化しまっている様なので、『Pythonでは、for文で取り出した値は必ずしも使用しなくてもいいものである』という風に認識を改めましょう。
    まだあまりご納得されていない様子ですが、まずはpythonのfor文に関する自身の抱いていた印象や認識が正しいものではなかったということから受け入れて頂ければ理解と納得が早まるかもしれません。

    キャンセル

回答 8

+4

理屈ではなくイメージとして想像しやすい様に
シンプルですがこれではいかがですか?
理解できる部分と、理解し難い部分の中間を取ったコードだと思いますが。。。

for n in ['taro','jiro','saburo','shiro']:
    print('hello' + n)

>> hello taro 
>> hello jiro
>> hello saburo
>> hello shiro

for文では、何も必ず取り出した要素(n)を使用しなければならないというルールはありません。
従ってhelloのみが出力されます。

for n in ['taro','jiro','saburo','shiro']:
    print('hello')

>> hello
>> hello
>> hello
>> hello

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/19 09:46

    コメント遅くなってしまいました。
    最初の「hello」4回に頭がとらわれてしまい、なかなか、頭が切り替えられない状況でした。

    >> hello taro
    >> hello jiro
    >> hello saburo
    >> hello shiro

    よりイメージしやすくなりました。ありがとうございますー。

    キャンセル

+3

太郎さん、次郎さん、三郎さん、四郎さんが列に並んでいて、

「一人ずつ前に進んで紙にお名前をお書きください」とお願いしたら紙には

太郎
次郎
三郎
四郎


と残るでしょうが
「お名前はけっこうですので前に進んで一人ずつ紙に✓を書き入れてください」とお願いしたら紙には

✓✓✓✓


と残りますよね。


(追記)

現実で「お名前はけっこうですので前に進んで一人ずつ紙に✓を書き入れてください」って言われたら「誰が並んでいたかは気にしてなくて、人数だけ知りたいんだな」って思いますよね。
それと同じでfor文でイテラブルから取り出した値が代入されている変数nがあって、でも「for文の本体でその変数を使っていない」と判明したら「どんな値がイテラブルから取り出されたかは気にしてなくて、個数だけが必要なんだな」とプログラマは思うわけです。


よいプログラマは

for unused in ['taro','jiro','saburo','shiro']:
    print('Hello')


として名前に意図を込めるとか、

for _n in ['taro','jiro','saburo','shiro']:
    print('Hello')


として命名規則で意図を込めるとか(値を使わない変数は_で始めるという慣習はPython界隈では通用します)、

for n in ['taro','jiro','saburo','shiro']:
    # 中身に関係なく個数分出力する
    print('Hello')


としてコメントにwhyを残すとかします。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/19 10:40

    「概念がつかめず」というのは、ご指摘の通りだと思います。そのため、言葉使いがクリアになっていなかったりして。失礼しました。

    本件から外れ恐縮ですが、全般的に、分からないことに対し、言葉で試行錯誤していくうちに、概念の理解に近づけるのではないかという、思いや願いのようなものがあるように思ったりもしています。

    >for文「が」イテレータ「から」['taro','jiro','saburo','shiro']の要素「を」一つずつ取り出していくわけですからね。

    このへんのニュアンスが、うまくつかめません。そして、このポイントに近づけないことが、理解の、さまたげになっているように思えます。どうぞ、宿題にさせてくださいませー。

    キャンセル

  • 2020/07/19 10:57

    > 言葉で試行錯誤していくうちに、概念の理解に近づけるのではないかという、思いや願いのようなものがあるように思ったり

    その通りだと思います。一方で、間違った言葉使いを指摘されることで修正されていくものでもあるので、必要以上に口酸っぱくなっていますがご容赦を。

    キャンセル

  • 2020/07/19 11:03

    いえいえ。助かっていますー。

    キャンセル

+1

もう少し、突っ込んだ因果関係を知りたいと思ったりしています。

何がわからないのでしょうか。ループに入ったnは、無視しても構いません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/15 17:23

    引っかかっているのは、「なんでこんなことをしているのだろう?」という違和感でしょうか?

    キャンセル

  • 2020/07/15 17:37 編集

    プログラムは「書いたとおり」に動作します。人間にとって意味があるかどうかとは関係なく、書かれたとおりに実行されます。

    キャンセル

  • 2020/07/15 17:54

    >(文法的にはコードが成立しているけど、「配列をループで回すけど中身を見ない」というのは不自然なの>で、現実的には書く機会はまずないとは思います)

    あるチュートリアルをみていて「?_」と思った次第です。現実的には、まず書かいないコードというご指摘、ありがとうございます。

    キャンセル

+1

元の回答

for 文のふるまいについて、こちらのドキュメントを参照すると良いかもしれません:
8. 複合文 (compound statement) — Python 3.8.4 ドキュメント

for_stmt ::=  "for" target_list "in" expression_list ":" suite
              ["else" ":" suite]

expression_list の結果対するイテレータが生成されます。
その後、イテレータが与えるそれぞれの要素に対して、
イテレータから返された順に一度づつ、スイートが実行されます。
...
その後、スイートが実行されます。
全ての要素を使い切ったとき
(シーケンスが空であったり、イテレータが StopIteration 例外を送出したときは、即座に)、
else 節があればそれが実行され、ループは終了します。

リンク先の説明で分かりにくい表現がいくつかりますので補足します

イテラブルオブジェクト

くり返し可能なオブジェクトのことで、
listdict などが該当します
用語集 — Python 3.8.4 ドキュメント

イテレーター

実際にくり返しを行うためのオブジェクトです
用語集 — Python 3.8.4 ドキュメント
組み込み型 — Python 3.8.4 ドキュメント

スイート

これは上記の for 文の構造の説明の中の suite の部分を示しています
ドキュメントが日本語訳されたときに
カタカナに変換されてしまっているため、わかりにくくなっています

追記

イテラブルオブジェクトには、要素を反復して取り出せるイテレータが付与されている。
この解釈は、合っていますでしょうか。

「要素を反復して取り出せるイテレータ」
この部分は正しいです

「イテラブルオブジェクトには、イテレータが付与されている」
付与されているとは限りません

イテラブルオブジェクトとイテレーターの関係については
次の記述が参考になるでしょう

用語集 — Python 3.8.4 ドキュメント

iterable
(list, str, tuple といった) 全てのシーケンス型や、 dict や ファイルオブジェクト といった幾つかの非シーケンス型、 あるいは Sequence 意味論を実装した iter() メソッドか getitem() メソッドを持つ任意のクラス

また、

組み込み関数 iter() の引数として渡すと、 オブジェクトに対するイテレータを返します

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/15 17:38

    貼っていただいたページをチェックしてみました。
    「イテラブルオブジェクト」「イテレーター」「スイート」それぞれの言葉のコンセプトは分からないのですが、説明文の行間より理解が進んだように思います。

    キャンセル

  • 2020/07/15 17:56

    説明を追記しました

    キャンセル

  • 2020/07/16 07:50

    イテラブルオブジェクトには、要素を反復して取り出せるイテレータが付与されている。この解釈は、合っていますでしょうか。

    キャンセル

  • 2020/07/16 11:58

    説明を追記しました

    キャンセル

+1

見える化しましたw

http://pythontutor.com

n には毎回代入が行われていますが、使用する箇所がないためスルーされています。
ってのが、視覚的に分かるかと。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/16 07:59

    皆様のご回答を拝読したあと、やってみると、「お!」という感じです。ありがとうございます。

    キャンセル

+1

仕組み

仕組みについては残念ながらあなたの直感はどうでもいい話です。
事実は動かしようがないので、直感と事実が違うならあなたの直感の方を事実に寄せてください。

for..in...がどういうモノなのかはy_shinodaさんの回答にもありますこちらを参照します。
8. 複合文 (compound statement) — Python 3.8.4 ドキュメント
これをものすごく簡単に要約すると

for n in ['taro','jiro','saburo','shiro']:
    何か

n = 'taro'
何か
n = 'jiro'
何か
n = 'saburo'
何か
n = 'shiro'
何か

と同じです。(breakcontinueとかあったら話は別ですが。)
「何か」(suite)の部分で、列挙したもの:n(target_list)を無視してはならないとはどこにも書いてませんし、
実際無視してもエラーにはならないので、質問文のnを使わないコードは合法です。

そう言語仕様が定まった理由

「なぜ列挙したものを無視してもいい言語仕様になっているか」についてはpythonを作った人に聞くしか無いので正確には言えませんが、
無視できなければ例えば「リストxsの個数だけ'hello'と表示する」という
「リストの中身はどうでもいいけど個数分だけ繰り返したい」場合にfor...in...で書けなくなって困るな、ということはわかります。

他の言語を見てみると、変数を置いておきながら使わないと、「使ってないけど大丈夫?」と気を遣って警告を出してくれる言語はいくつかあります。
例えばswiftは「使わないならそうと分かるように変数名を_にしろ」と警告を出してきます。

for i in 0..<10 {
    print("hello")
}
main.swift:2:5: warning: immutable value 'i' was never used; consider replacing with '_' or removing it
for i in 0..<10 {
    ^
    _

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/20 11:36

    ご回答ありがとうございます。参考にします。

    キャンセル

0

見える化しました

for index, value in enumerate(['taro','jiro','saburo','shiro']):
    print('index:{}, value:{},'.format(index, value) + ' Hello')

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/15 17:52

    すみません、index、valueという言葉は適切ではなかったかも知れません〜。

    キャンセル

  • 2020/07/15 21:39

    ■これは分かるが
    for value in ['taro','jiro','saburo','shiro']:
    print(value)
    print(' Hello')

    ■これは分からない
    for value in ['taro','jiro','saburo','shiro']:
    #print(value)
    print(' Hello')

    という事?
    コメントアウトした瞬間に疑問が湧くということ?

    キャンセル

  • 2020/07/15 21:39

    インデントなくなってもーた

    キャンセル

0

この場合の関係は、「リストの要素の個数分、繰り返し実行される」というだけですね。
繰り返される処理にnの値が使われないことに違和感があるのでしょうが、実世界でも、
「並んでいる人数分、握手して微笑む」みたいな繰り返し処理をすることがありますね。
この場合、相手が誰かは関係なく、並んでいる人数分、動作を繰り返すだけです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/16 07:56

    「相手が誰かは関係なく、並んでいる人数分、動作を繰り返すだけです」
     だんだん感じがつかめて来ました。ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.81%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る