問題の背景
Pythonのイテレータの一種にジェネレータなるものがあるらしい。
よし、どういう動作をするのか確かめてみよう。
参考になるページも見つけたし、早速やってみるか。
[参考にさせて頂いた記事]
Pythonのイテレータとジェネレータ
エラーになったコード
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
gen.next()
gen.next()
gen.next()
・想定した結果
1
2
3
・現実の結果
AttributeError: 'generator' object has no attribute 'next'
・環境
Python3.6
原因
AttributeErrorってまず何やねんってレベルなのでひとまず検索。
すると早速素晴らしい記事を発見。
[参考にさせて頂いた記事]
Pythonエラー一覧(日本語)
こちらの記事によると
Attribute系(AttributeError)
AttributeError: 'X' object has no attribute 'Y'
'X'オブジェクト(Xにはstrやmoduleなどの型名が入ります)は'Y'という属性なんて持ってないよ!
本当にXはYという属性を持っているか、スペルミスしていないか確認しましょう。
そもそもAttributeってPythonの文脈では**「属性」**って訳するんですねえ。
ということは オブジェクト'gen' が 属性'next' を持っていないことが原因といえるようですね。
解決方法を探る
そもそもオブジェクト'gen'って何者?
さらっと
gen = my_generator()
なんて書いてるけど、my_generator()
って関数だよね?
じゃあ型は何やねーん、ってことで調べた。
gen = my_generator()
type(gen)
結果
<class 'generator'>
generatorクラス……聞いたことがなかったですね。
generatorクラスのメソッド
Python3.6.1のドキュメンテーションによると、generatorクラスには以下のメソッドがあるようです
generator.__next__() generator.send(value) generator.throw(type[, value[, traceback]]) generator.close()
generator.next()
じゃなくてgenerator.__next__()
なのか!
これで解決できそうですね
修正後
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
gen.__next__()
gen.__next__()
gen.__next__()
・結果(理想=現実)
1
2
3
解決!
ちなみにPython2系だとnext()
メソッドが正しいようですね。
それを知らずPython3系の環境にコピペしたのが間違いでした。
結論
Python3系において、generatorクラスの、関数を実行するメソッドの名前はnext()
ではなく__next__()
初学者らしいつまずきを初学者らしく克服できてよかったと思います。
ここまで読んでくださってありがとうございました!