疑念は探究の動機であり、探究の唯一の目的は信念の確定である。

数学・論理学・哲学・語学のことを書きたいと思います。どんなことでも何かコメントいただけるとうれしいです。特に、勉学のことで間違いなどあったらご指摘いただけると幸いです。 よろしくお願いします。くりぃむのラジオを聴くこととパワポケ2と日向坂46が人生の唯一の楽しみです。

番外編: python2とpython3の違いについてのまとめ

ごぶさたです。

最近はずっと何も書けない状態が続いています。4月から始めた仕事も少しずつですが慣れてきました。

現在、私はプロジェクトに参加していて、そこではPython2でプログラムを書いています。上司に「このプロジェクトには続きがあって、第二弾がこれからある」と言われました。
そのとき私は「現在ではPython2で書かれていますが、第二弾はPython3で書かれるのですか?」と尋ねました。 すると「引き続き、2で書く。3で書こうとするならば、ほとんど最初から書き直さなければならないからね。 続編のプロジェクトだから今やっているプロジェクトで使われているプログラムを使う。」と答えました。
また、友達に「いま参画しているプロジェクトではPython2で書かれている」と伝えたら、「それは大変だね」と同情されました。

そんな話を聞かれたので「Python2とPython3はそれほどまでに違うのか?」と思いました(今でも少しそうです)。


そこで今回は、私が気づいたPython2とPython3の違いについてまとめてみたいと思います。
またこれは違いがわかり次第、何回も更新して追記したいと思います。

プリント関数について

Python2では「print "Hello"」でもOKですが、Python3だとエラーになります。カッコ()がないとエラーが出ます。

#Python2だとOKだが、Python3だとエラーが表示される。
print "Hello"


#Python3では次のようにカッコ()を使わなければならない。
print("Hello")

辞書型について

Pythonには辞書型というものがあります。リスト型やタプル型などと同じような感じです。書き方はPython2と3では同じですが、少し異なっているところもあります。
基本的には辞書型は次のように書きます。

#辞書型の基本形
dictionary = {'key1': 'value1', 'key2': 'value2'}
dict_key = dictionary.keys()
dict_value = dictionary.values()
print(dict_key)
print(type(dict_key))
print(dict_value)
print(type(dict_value))

すると、dict_keyではkeyの部分が得られて、dict_valueにはvalueの部分が得られます。つまり、dict_keyでは「'key1' 'key2'」が得られて、dict_valueでは「'value1' 'value2'」が得られます。
問題はそのような要素の集め方です。Python2と3では次のような違いが生じます。
まずはPython2のほうです。

#Python2での上のプログラムの結果

#dict_key
['key1', 'key2']

#dict_keyの型はリスト型
<class 'list'>


#dict_value
['value1', 'value2']

#dict_valueの型はリスト型
<class 'list'>

つまり、こちらではリスト型となります。


他方、Python3では次のようになります。

#Python3での上のプログラムの結果

#dict_key
dict_keys(['key1', 'key2'])

#dict_keyの型はdic_key型
<class 'dict_keys'>


#dict_value
dict_values(['value1', 'value2'])

#dict_valueの型はdic_value型
<class 'dict_values'>

つまり、Python3ではそれぞれdict_keys型とdict_values型となり、リスト型ではありません。したがって、python3のときはリスト型に変換してから、要素をとるといったことをしなければなりません。
次のプログラムはPython2では正常に動きますが、3ではエラーが発生します。

#Python2では正常に動くが、3ではエラーが発生する。
dic = {"apple":1, "banana":2}
dic_key = dic.keys()
dic_value = dic.values()
print(dic_key[0])
print(dic_value[0])

#Python2では次の結果が出る。
#print(dic_key[0])
"apple"

#print(dic_value[0])
1


もしもPython3で上と同じようにしたい場合は、dic_keys型やdic_values型をリスト型に変換してからしなければなりません。

#Python3で正常に動かすために

dic = {"apple":1, "banana":2}
dic_key = dic.keys()
dic_value = dic.values()
print(list(dic_key)[0])
print(list(dic_value)[0])

#結果
"apple"
1

unittestについて

unittestというモジュールがあります。それについてPython2と3はかなり異なっています。

インポートについて

Python2ではpipでインストールしなければなりません(標準ライブラリではありません)。pipでインストールした後、インポートするときは次のように書きます。

#Python2でのunittestのインポート
import unittest
from mock import patch
from mock import mock_open


ここで、もしも「from unittest.mock import patch」と書くとエラーが出ます。しかし2.7の説明書ではそのような書き方でインポートしています。ですので、もしかしたらこの書き方でも大丈夫なのかもしれません。
https://cpython-test-docs.readthedocs.io/en/latest/library/unittest.mock.html


他方でPython3においてはunittestは標準ライブラリです。インストールする必要はありません。インポートするときは次のように書きます。

#Python3でのunittestのインポート
from unittest.mock import patch, mock_open

逆に、先ほどのPython2のように

import unittest
from mock import patch

と書くとエラーが生じます(理由はわかりません)。

open関数にパッチをかける方法について

Python2では「'__builtin__.open'」と書きますが、Python3では「'builtins.open'」と書きます。
(例はいつか書きます)。

追記 2019/07/02: 組み込み関数range()について

Python2では、range()とxrange()があります。ですが、Python3ではrange()のみしかありません。

#Python2でのrange()関数の基本
print(range(3))

#結果
[0, 1, 2]


#型はリスト型。
print(type(range(3)))

#結果
<type 'list'>

xrange()関数はprint()で出力しても中身の数字は表示されません。型はxrange型という特別なものです。

#Python2でのxrange関数の基本

print(xrange(3))
print(type(xrange(3)))

#結果
xrange(3)
<type 'xrange'>


xrange関数はfor文などで使われます。もちろんrange関数でも問題ありません。

#range関数でのfor文
for i in range(3):
    print(i)

#range関数での結果
0
1
2


#xrange関数でのfor文
for i in xrange(3):
    print(i)

#xrange関数での結果
0
1
2


このようにPython2ではxrange関数が使えますが、Python3ではxrange関数はエラーが生じます。つまり、使えません。

print(xrange(3))

NameError                                 Traceback (most recent call last)
<ipython-input-12-50e3fec3bafd> in <module>
----> 1 print(xrange(3))

NameError: name 'xrange' is not defined


さらにPython3ではrange()はrange型です。リスト型ではありません。

#Python3でのrange関数の基本
print(range(3))
print(type(range(3)))

#結果
range(0, 3)
<class 'range'>


明示的にrange()を表示するならば、リスト型に変換する必要があります。また、Python2のxrange()と同じように、for文に対してこのままrange(3)を使うことができます。

#range関数を明示的にリスト型に変換する。
print(list(range(3)))

#結果
[0, 1, 2]


#for文に対して、リスト型に変換する方法。
for i in list(range(3)):
    print(i)

#結果
0
1
2

#for文に対して、range関数をそのまま使う方法。
for i in range(3):
    print(i)

#結果
0
1
2


普通、for文のときは、リスト型に変換せずに、for i in range(3): と使います。







僕から以上