Pythonでのsetは破壊的な挙動なのか?

投稿者: Anonymous

setについて意図と異なる挙動が有り調べても解決できなかったため質問させてください。

このプログラムを実行しますと、

プログラム

d = map(int, [i for i in range(5)])
print(type(d))
print(len(set(d)))
print(type(d))
print(len(set(d)))

このような結果が得られます。

実行結果

<class 'map'>
5
<class 'map'>
0
<class 'map'>

質問

一回目のprint(len(set(d)))は5を返します。二回目のprint(len(set(d)))も同様に5を返す思っていたのですが、0を返してしまう理由を教えていただきたいです。
一回目と二回目の間で特にdはいじっていないので同じ結果が得られるかなと思っています。
もしありえるとしたらsetが変数dを破壊的に変更しているとかあるのかなと思ってます。

環境

Python 3.7.0

よろしくおねがいします。

解決

set が破壊的なのではなく、ジェネレーターが破壊的なのです。
map()が返すのはリストではなく、ジェネレーターです。
ジェネレーターは一度取り出した中身は失われ、次に取り出すものは前回の続きになります。
このため、 ‘set(d)’ とした時点で、ジェネレーターdの中身がすべて取り出され、次に同じことをしても既にdは空になっています。

d = [int(i) for i in range(5)]

こうやって作った場合、dはリストとして作られるため、何度でも中身を取り出せます。

あるいは以下のように、setの結果を変数に代入しておいてもよいでしょう。

d = map(int, [i for i in range(5)])
s = set(d)  # ここでdは空になる
print(len(s))
print(len(s))
回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *