読者です 読者をやめる 読者になる 読者になる

paiza開発日誌

IT/Webエンジニア向け総合求人・学習サービス「paiza」(https://paiza.jp ギノ株式会社)の開発者が開発の事、プログラミングネタ、ITエンジニアの転職などについて書いています。

Python初心者が2系→3系への移行時に意外と気づかないけど、知らないままだと危険な変更点

f:id:paiza:20161220122202j:plain
Photo by Yuya Tamai
秋山です。

私は主にPythonを使って開発をしているのですが、Python2系とPython3系にはいろんな変更点があります

で、互換性がない変更点も割とあって、よく知らないまま初心者が2系から3系に移行しちゃうと結構危険なところもあるので、今日はその辺の話をしていきます。

print に括弧が必要になっちゃったよねーみたいな話や、よく言われている raw_input とか xrange の話は飛ばします。

■意外と気をつけたいPython3系における変更点

◆map,filter,zipがイテレーターを返してくる

Python2系ではmap, filter, zipともに普通のリストを返していますよね。

map_object = map(int, "12345")
print(list(map_object))
print(list(map_object))

この場合、3系だと2回目の出力でリストの中身は空になります。イテレーターなので。

sumも同様です。

next(map_object)

を実行すると、返した値が消えます。

これは当然、for文やリスト内包表記で使っても消えてしまいます。

既にPython2系でもイテレーターを使ったことがある人にはなじみのある動作で「当たり前やんけ」と思うかもしれません。が、あまりイテレーターなどに触れたことがない人、「mapとかfilterとかzipって、つまりリストでしょ」と思い込んでいる人が、気付かずPython3系に移行して使うと重大なバグを生みそうな部分ではあると思います。

iterator の .next() が名前変更されて __next__() になった。

本来は __eq__, __len__ などと同等に扱われるべきだったのにずっと残っていたのが、3系になってやっと変更になった部分です。

リストが list.__len__() という関数を持っていて、組み込み関数の len() で長さが取得できる……というのと同じように、イテレーターも iterator.__next__() という関数を持っていて、組み込み関数の next() を使えばイテレータの次が取得できる……というやり方にした方が一貫性があるよね、ということで変更されたようです。

Python2では iterator.next() と next(iterator) が両方使えましたが、Python3では next(iterator) しか使えないので注意しましょう。

◆dictなどのitems()で返ってくるのが、リストでもイテレーターでもなくビューオブジェクトになった

dict の items,values,keys で、2系ではリストが返ってきていましたが、3系ではビューオブジェクトを返すようになりました。2系であった、 iteritems などイテレーターで取得する手段もなくなりましたね。

ビューオブジェクトはリストでもイテレーターでもないので

d = {'a':1,'b':2,'c':3}
dict_items = d.items()
print(next(dict_items))
print(dict_items[1])

上記のように、nextを使って値をイテレーター的に取得することも、リストとして取得することもできません。

d = {'a':1,'b':2,'c':3}
dict_items = d.items()
for i in dict_items:
     print(i)

上記のようなループ処理では使えます(帰属演算子 in が使えるということです)。

len() を使って総数を確認することや iter() でイテレーターを作ることもできますので、 iteritems() と同等の処理をしたいときはこちらを利用できます。

ビューオブジェクトの詳細はこちらを参照してください。
4. 組み込み型 — Python 3.5.2 ドキュメント

◆リスト内包表記の変数のスコープが外に漏れなくなった

[i for i in range(3)]
print(i)

このコードですが、

↓こちらは【Python2】です、実行してみてください。
エラーにならず、 i の値が普通に出力されます。

↓一方、【Python3】では……実行してみてください。
i のスコープがリスト内包表記の外に漏れないので、 i が未定義ということでエラーになります。

2系ではリスト内表記の i を内包表記外で使えていたのですが(それ自体コードの書き方としてあんまりよくないんですが……)、3系だと想定外の i が出てきたということでエラー扱いされるようになりました。

◆地味に使えていた <> 演算子が使えなくなり、使えるのは != だけになった

SQLなどでも使う演算子 <> が、3系では使えなくなっています。

現実的には、2系でもほとんどの人が != を使っていたと思うのでトラブルが起こる可能性は低いかと思いますが、3系では廃止されているので要注意ということで。

◆a,b,c = (1,2,3) のような代入のとき、 *a, b, c = (1,2,3,4) というような書き方ができるようになった

a, *b, c = (1,2,3,4,5)
print(a, b, c)

このようなコードの出力結果は

1 [2, 3, 4] 5

となります。

ちなみに

a, *b, *c = (1,2,3,4,5)

みたいな書き方は当然ですが不可能ですので。

便利に使えそうな気もする一方で微妙にわかりづらい書き方ですが、Python3系の場合は誰かがこんなふうに書いている可能性がなきにしもあらずなので要注意です。

■まとめ

これだけじゃなく、2系と3系の間にはほかにもいろいろな変更が入っているので、詳しく知りたい人は公式ドキュメントを見てみましょう。

公式なので当然ですが、2→3の大きな変更以外にも、3.4→3.5などの細かーい変更に関しても詳しく書かれています。
What’s New in Python — Python 3.5.2 ドキュメント


あと途中でブログパーツとして使ったオンライン実行環境サービス「paiza.IO (パイザ・アイオー)」はこちら

Python2・3はもちろん、ブラウザだけで多数言語のコードを実行することができちゃいます。2系と3系で同じコードを書いた時の動作の違いとかもすぐに確認できますので、気になる人は使ってみてください。
Web-based online coding environment | paiza.IO

Pythonの学習レッスン動画も公開中!プログラミング学習コース

f:id:paiza:20160830130051j:plain
paizaでは、未経験者でも動画を通してプログラミング等が学べる「paizaラーニング」を公開しております。

paizaラーニングでは、paizaの人気美少女キャラクター霧島京子(cv:上間江望)が、かわいい声で優しく・楽しく・わかりやすくプログラミングを教えてくれます。「霧島京子による1本3分程度のレッスン動画」に加え、「ブラウザ上でコードを書いて実行できるオンライン実行環境」「複数の練習問題」で、初心者でも無理なくプログラミングを習得することができます。

paiza.jp




paizaではスキルのあるエンジニアがきちんと評価されるようにし、技術を追い続ける事が仕事につながるようにする事で、日本のITエンジニアの地位向上を図っていければと考えています。特にpaizaではWebサービス提供企業などでもとめられる、システム開発力や、テストケースを想定できるかの力(テストコードを書く力)などが問われる問題を出題しています。

テストの結果によりS,A,B,C,D,Eの6段階でランクが分かります。自分のプログラミングスキルを客観的に知りたいという方は是非チャレンジしてみてください。

http://paiza.jp

プログラミング入門講座|paizaラーニング

PHP入門編Ruby入門編Python入門編Java入門編JavaScript入門編C言語入門編C#入門編アルゴリズム入門編