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

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

新規登録して質問してみよう
ただいま回答率
85.31%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

4回答

1064閲覧

Python3のenumerate関数の仕組みを理解したいです(超初心者)

zabuton

総合スコア12

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

1グッド

1クリップ

投稿2019/01/25 06:32

前提・実現したいこと

Python3のenumerate関数の仕組みについてご教授ください。

発生している問題・エラーメッセージ

enumerateを使ってエラーにはなりませんが、該当のソースコードを書いて、なぜ出力結果が

0 ああああ
1 いいいい
2 うううう
3 ええええ

となるのかについて、流れというか、原理のようなものを私は理解できていません。
今日teratailの存在を知ったくらいの超初心者でして、enumerateを使ったプログラムを書くことはできますが、検索しても理解できないため、少しひねった問題や応用になると、全く解けなくなってしまいます。

該当のソースコード

Python3

1text = [“ああああ“, 2 “いいいい“, 3 “うううう“, 4 “ええええ“] 5for i,j in enumerate(text): 6 print(i, j)

試したこと

「Python3 enumerate」でググって、公式ドキュメントを見たところ、「enumerate オブジェクトを返します」とありました。この公式ドキュメントの解説は、ほとんどが関数やソースコードを用いたもので、私の知識では理解できませんでした(https://docs.python.jp/3/library/functions.html#enumerate)。

firedfly👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2019/01/25 06:43

『仕組み』というとちょっとざっくりしすぎな気がします。 特に何がしっくりとこないのか、もう少し細かいテーマにできませんか。
zabuton

2019/01/25 10:30 編集

分かりづらい質問ですみません…。もう少し細かくすると、「プログラミング全般で、enumerateはどんな動作をする関数なのか? Pythonの場合どうなるのか?」という質問になります。 backyardさんから回答を貰って気がついたのですが、私はPythonについて「何が分かっていないのかが分かっていない」レベルで、まずプログラミングの常識や考え方から知る必要があるのだろうと思います。
LouiS0616

2019/01/25 10:38

enumerateはPythonで提供されている関数であって、プログラミング一般で用いられるものでは無いですよ。類似のものは言語に依ってはあるのかもしれませんが。
zabuton

2019/01/25 12:49 編集

すみません、また誤解していました…。うーん、teratailは思ったよりずっと専門的に高度な人々が集まる場所と言うべきか。今の私には、yahoo知恵袋などのほうが向いているのかもしれません。
LouiS0616

2019/01/25 13:09 編集

能動的に知識を深めようとしている人は、teratailでは歓迎されます。 zabutonさんが各回答の趣旨を理解しようする姿勢は非常に強く感じますので、teratailが向かないということは無いと思いますよ。 もちろん知恵袋でも有用な回答が得られることもありますので、試してみると良いのではないでしょうか。 マルチポストさえしなければ、両サービスのイイトコ取りをしてしまうのもアリです。
guest

回答4

0

  • for 文が何をしているのか。
  • 多重代入が何か。

が分かれば、理解できるのだと思います。

for 文

for 文は、

python

1for <変数> in <iterable>: 2 <変数を使った body>

という感じになると思います。以下、ざっくりとした説明になります。

for 文では、まず、<iterable> は、iter(<iterable>) によって <iterator> に変換されます。要は iter 関数の引数になりうるオブジェクトが <iterable> な訳です。なお、<iterator> は、<iterable> でもあり、<iterator> を引数にして iter を実行すると <iterator> そのものが返ってきます。generator オブジェクトや map オブジェクトなどは。初めから iterator です。

その上で、for 文は、変換された <iterator> を引数として、関数 next を実行し、その戻り値を <変数> に代入して、<body> の処理が行われます。これは、<iterator> の値が尽きて、StopIteration という例外が発生するまで繰り返されます。

python

1for i in [1, 2, 3]: 2 print(i)

この例で説明してみます。リストは iterable です。まず、iter([1, 2, 3]) で iterator ができます。これを引数として関数 next を実行すると、変数 i1 が代入され、print(1) が実行されます。もう一度 next が実行されると、今度は i2 が代入されます。
このような処理が、元々のリストの要素が尽きるまで続きます。

多重代入

次に、多重代入です。

python

1x, y = (1, 2)

x1 が、y2 が代入されるというものです。

最後

enumerate(<iterable>) を実行すると、新たな <iterator> オブジェクトが返ってくるのですが、そのオブジェクトを引数にしてに next 関数を実行すると、(<0から始まる数字>, <iterable の要素>) というタプルが返ってきます。

そういう訳で、

python

1for i, x in enumerate(['a', 'b', 'c']): 2 <body>

を実行すると、

  • `enumerate' によって新たな iterator オブジェクトが作られる。
  • next の実行により、タプル (0,'a') が返される。
  • i0 が、x'a' が代入され、<body> が実行され、それが繰り返されて、4回目で StopIteration が発生して終了します。

以上、ざっくりした(比喩的な)説明でした。

投稿2019/01/26 11:01

kts_h

総合スコア207

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zabuton

2019/01/27 16:09

ありがとうございます。私の知識と理解力では繰り返し読む必要がありますが、それでも助かります。 今までは理解というよりは単に指先の「慣れ」だったのですが、皆様のアンサーと、特に「多重代入」という用語を知ったことで改善してきました。「`enumerate'を使えば『要素のインデックス』および『要素』が同時に取得される」ということが、少しは目や頭で理解出来てきたと思います。
guest

0

とりあえずちょっとPythonから離れて、enumerateで取得できるデータがどういう風になっているかを……。

昔ながらのプログラミング言語では、たくさんのデータを繰り返しで処理する場合

  1. 1番目のデータを処理する
  2. 2番目のデータを処理する
  3. 3番目の……

というように何番目のデータを扱うかを指定して繰り返していましたが、全部で何個あるかなどを知っていないといけなかったり、面倒なので、データの入れ物自体に細工して以下のようなモノが用意されるようになりました。

  • 次のデータをください、とお願いされると、入れ物の中の未処理の1個を渡す。

 (こういう機能のことをリンク先の説明ページでは「イテレーションをサポートする」と書いてます)

  • 全部処理し終わったら、次がないと言うことを知らせる。

こういうデータの入れ物がPythonでの「enumerateオブジェクト」です。Pythonのfor文などが実際に動く際には、このenumerateオブジェクトタイプの入れ物に対して「次の1個を出して!」という依頼を繰り返し、データを取り出しながら処理を進められるように作られています。
同じような機能を持つデータの入れ物は他のプログラミング言語にもあり、だいたい似たような名前がついているので、案外「根本的な仕組みの説明」が無いのかも知れませんね(なかば常識的な機能になっている)。

とりあえず難しい話抜きで動きの方からこんなもの、というのを書いてみましたが、参考になれば……。

投稿2019/01/25 07:50

backyard

総合スコア534

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zabuton

2019/01/25 10:19

基礎から説明していただけて本当にありがたいです。なるほど、私はプログラミングに関してPythonの入門レベルしか知らないので、質問に「Python」と書いてはいましたが、本当に私が探していたのはプログラミングの「根本的な仕組みの説明」なのだろうと思います。「私は何が分からないのか」が、やっと分かったと言うか。
backyard

2019/01/25 23:57

プログラミング言語やプログラムが動く仕組みも人間が開発したものなので、その裏側の仕組みなどに眼を向けられると理解が加速するのですが……最初からそういう風にやってるといずれ行き詰まります(簡単な例え話や言い換えでは理解できない領域が絶対あるので)。最初は「なんだかよくわからないけれど、こうしたら、こうなった」をたくさん蓄積して、まずはPythonでもなんでも1つのプログラミング言語で「仕掛けはよくわかんないけど、とりあえず動かせないことはない」というくらいになるのが案外早道です。また、1つの言語をある程度使えると、別の言語を学ぶときも「これは、Pythonでいう、あれだな」という理解で進められるので楽になります。 おためしあれ。
zabuton

2019/01/26 06:07

実は最初、仕組みや原理を学ぼうとまではほとんど考えていませんでした。最初に調べた時は、仰るように「簡単な例え話や言い換えでは理解できない領域が絶対ある」と痛感しました。それで、とにかく動かせるようになれればいい、どうしても必要な場合は少しは仕掛けを調べよう、と考えてました。 しかし割とすぐに行き詰まって、知恵をお借りした次第です。以前よりは、繰り返し処理や「オブジェクト」等々に関する仕掛け・考え方が分かるようになってきました。まずは一番慣れているPythonを土台として、実践していこうと思います。
guest

0

PythonのREPLでも試せるのでやってみましょう。
for で繰り返されているのはこのような動作です。
a をチェックしたときにリストではなくて enumerate オブジェクトになっています。

>>> a = enumerate([1,2,3,4]) >>> a <enumerate object at 0x10c2e51b0> >>> a.__next__() (0, 1) >>> a.__next__() (1, 2) >>> a.__next__() (2, 3) >>> a.__next__() (3, 4) >>> a.__next__() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration

次に、 i, j の代入についてですが、タプルという単語を調べましょう。
a.__next__() のときの返り値である、 (0, 1) というのがそのタプルなのですが、ここでは2つの値を並べたものです(配列とは違います)。
タプルは次のように個別に変数に代入できます。

>>> i, j = (0, 1) >>> i 0 >>> j 1

タプルの1つ目の値である i は添字です。この場合は配列のインデックスですね。 l = [1,2,3,4] に対して l[0] と呼び出すときの値です。連想配列のキーなどである場合もあるので常に整数とは限りません。
j はその添字に対応する配列の値が出ています。

このような説明でわかるでしょうか?

投稿2019/01/25 10:04

mather

総合スコア6762

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zabuton

2019/01/25 12:45

お気持ちはありがたいのですが、REPLというものは初耳で、私のレベルでは理解できませんでした…。
mather

2019/01/28 01:44

「REPL」を検索してみましたか? python コマンドを引数無しで実行したら出てくるコンソールのことですよ。
zabuton

2019/01/28 03:12

はい、25日の時に検索しましたが、知らない言葉ばかりでほとんど分かりませんでした…。「REPL python」と検索しても、やはり挫折しました。 主にpaizaとprogateで学習しているため、REPL・コマンド・コンソールといった知識(常識?)の欠けていることが、理解できない原因かと思います。
guest

0

ベストアンサー

こんにちは。
どのレベルから説明すればいいかわからないので、まずは触りを。

下は text_list からひとつずつ text を取り出して表示するコードです。

Python

1text_list = ["ああああ", "いいいい", "うううう", "ええええ"] 2 3for text in text_list: 4 print(text)

下は text_list を text_enum(要素ごとに連番を付与したlist※) に変換し、
text_enum からひとつずつ index と text を取り出して表示するコードです。

 ※正確には list ではなく generator で、 for で要素を取り出すたびに連番を生成しています

Python

1text_list = ["ああああ", "いいいい", "うううう", "ええええ"] 2text_enum = enumerate(text_list) 3 4for index, text in text_enum: 5 print(index, text)

さらに下は text_enum の中身を模式的に再現したコードです。

Python

1text_list = ["ああああ", "いいいい", "うううう", "ええええ"] 2text_enum = [(1, "ああああ"), (2, "いいいい"), (3, "うううう"), (4, "ええええ")] 3 4for index, text in text_enum: 5 print(index, text)

ここまででわからないことはありますか?

投稿2019/01/25 06:51

編集2019/01/25 07:10
firedfly

総合スコア1133

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zabuton

2019/01/25 12:43

ありがとうございます。分からない部分は、「text_enum」です。ググったら、generatorという機能があるんですね。「text_enum」が、text_listを変換するgeneratorである。とすると「text_enum」というgenerator名は、「text_list_enumerate_generator」の意味なんでしょうか?
firedfly

2019/01/25 12:47

理解が早いですね。その通りです。3つ目の例のような「連番と要素のタプルを生成するgenerator」を返すのがenumerate関数です。 気は早いですが、自作のgeneratorを使えるようになると、ぐっとPythonらしいコードになりますよ。
zabuton

2019/01/25 13:08

得心がいきました、どうもありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問