多くのPython初心者は、Pythonのどのバージョンから始めるべきか悩んでいます。
しかし、もしあなたが新しいプロジェクトを始めようとしていて、選ぶべき選択肢があるとしたらどうでしょうか? Python 2.7.xとPython 3.xの両方が使用しようとしているライブラリをサポートしていれば、現在のところ「正しい」も「間違っている」もないと言えるでしょう。 しかし、Python の最も人気のある 2 つのバージョン間の主な違いを見ておくことは、どちらかのコードを書くとき、またはプロジェクトを移植しようとしているときに、共通の落とし穴を避けるために価値があります。
セクション
- セクション
-
__future__
モジュール - print 関数
- Python 2
- Python 3
- 整数の割り算。
- Python 2
- Python 3
- Unicode
- Python 2
- Python 3
- xrange
- Python 2
- Python 3
-
__contains__
メソッドの
range
オブジェクトに対する Python 3 での処理- Python 2 と 3 の速度差についての注意点
- 例外の発生について
- Python 2
- Python 3
- 例外の処理
- Python 2
- Python 3
- Python 2
- Python 3
- Python 2
- Python 3
- Python 2
- Python 3
- Python 2
- Python 3
- Python 2
- Python 3
- Python 2
- Python 3
The __future__ module
Python 3.xではPython 2と互換性のないキーワードや機能が導入されており、Python 2では内蔵された__future__
モジュールを介してインポートすることができます。 Python 3.x のサポートを計画している場合は、__future__
インポートを使用することをお勧めします。 例えば、Python 3.xの整数除算の動作をPython2で実現したい場合、
from __future__ import division
__future__
モジュールからインポートできるその他の機能を以下の表に示します。
feature | optional in | mandatory in | effect |
---|---|---|---|
nested_scopes | 2.1.0b1 | 2.2 | PEP 227:Statically Nested Scopes |
generators | 2.2.0a1 | 2.3 | PEP 255:Simple Generators |
division | 2.2.0a2 | 3.0 | PEP 238:分割演算子の変更 |
absolute_import | 2.5.0a1 | 3.0 | PEP 328:Imports: |
with_statement | 2.5.0a1 | 2.6 | PEP 343:with ステートメント |
print_function | 2.6.0a2 | 3.0 | PEP 3105:Make print a function |
unicode_literals | 2.6.0a2 | 3.0 | PEP 3112:Bytes literals in Python 3000 |
from platform import python_version
プリント関数
非常に些細なことです。 そして、print-syntaxの変更はおそらく最も広く知られている変更ですが、それでも言及する価値があります。 Python 2 の print 文は print()
関数に置き換えられました。つまり、印刷したいオブジェクトを括弧で囲む必要があります。
Python 2 では追加の括弧があっても問題はありませんが、対照的に、Python 3 では、括弧なしで Python 2-way で print 関数を呼び出すと SyntaxError
が発生します。
Python 2
print 'Python', python_version()print 'Hello, World!'print('Hello, World!')print "text", ; print 'print more text on the same line'
Python 2.7.6Hello, World!Hello, World!text print more text on the same line
Python 3
print('Python', python_version())print('Hello, World!')print("some text,", end="")print(' print more text on the same line')
となります。
Python 3.4.1Hello, World!some text, print more text on the same line
print 'Hello, World!'
File "<ipython-input-3-139a7c5835bd>", line 1 print 'Hello, World!' ^SyntaxError: invalid syntax
注意点です。
上記のPython 2による「Hello, World」の印刷は、ごく「普通」に見えました。 しかし、print
はPython2では関数呼び出しではなく「ステートメント」なので、括弧内に複数のオブジェクトがある場合はタプルを作成することになります。
print 'Python', python_version()print('a', 'b')print 'a', 'b'
Python 2.7.7('a', 'b')a b
整数の割り算
この変更は、コードを移植している場合は特に危険です。 なぜなら、整数分割の動作の変更は、しばしば気づかれないからです (それは SyntaxError
を発生させません)。
だから、私はPython 2の人たちの手間を省くために、Python 3のスクリプトでは3/2
float(3)/2
3/2.0
を使う傾向があります(その逆もあります。
Python 3 のスクリプトでは 3/2
3/2
を使うようにしています。)
Python 2
print 'Python', python_version()print '3 / 2 =', 3 / 2print '3 // 2 =', 3 // 2print '3 / 2.0 =', 3 / 2.0print '3 // 2.0 =', 3 // 2.0
Python 2.7.63 / 2 = 13 // 2 = 13 / 2.0 = 1.53 // 2.0 = 1.0
print 'Python', python_version()print '3 / 2 =', 3 / 2print '3 // 2 =', 3 // 2print '3 / 2.0 =', 3 / 2.0print '3 // 2.0 =', 3 // 2.0
Python 2.7.63 / 2 = 13 // 2 = 13 / 2.0 = 1.53 // 2.0 = 1.0
Python 3
print('Python', python_version())print('3 / 2 =', 3 / 2)print('3 // 2 =', 3 // 2)print('3 / 2.0 =', 3 / 2.0)print('3 // 2.0 =', 3 // 2.0)
Python 3.4.13 / 2 = 1.53 // 2 = 13 / 2.0 = 1.53 // 2.0 = 1.0
Unicode
Python 2ではASCIIのstr()
byte
タイプはありません。
さて、Python 3では、ついにUnicode(utf-8)のstr
byte
bytearray
sです。
Python 2
print 'Python', python_version()
Python 2.7.6
print type(unicode('this is like a python3 str type'))
<type 'unicode'>
print type(b'byte type does not exist')
<type 'str'>
print 'they are really' + b' the same'
they are really the same
print type(bytearray(b'bytearray oddly does exist though'))
<type 'bytearray'>
Python 3
print('Python', python_version())print('strings are now utf-8 \u03BCnico\u0394é!')
Python 3.4.1strings are now utf-8 μnicoΔé!
print('Python', python_version(), end="")print(' has', type(b' bytes for storing data'))
Python 3.4.1 has <class 'bytes'>
print('and Python', python_version(), end="")print(' also has', type(bytearray(b'bytearrays')))
and Python 3.4.1 also has <class 'bytearray'>
'note that we cannot add a string' + b'bytes for data'
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-13-d3e8942ccf81> in <module>()----> 1 'note that we cannot add a string' + b'bytes for data'TypeError: Can't convert 'bytes' object to str implicitly
xrange
Python 2.xではxrange()
の使い方が非常にポピュラーです。xでは、イテレート可能なオブジェクトを作成するために、例えば。
その動作はジェネレータに非常に似ていますが、「遅延評価」と呼ばれるものです。 “
その「遅延評価」のおかげで、通常の range()
xrange()
が (for-loop などで) 1 回だけ反復しなければならない場合、一般的に高速になることです。) しかし、1回の反復とは対照的に、反復を複数回繰り返す場合は、生成が毎回ゼロから行われるため、お勧めできません!
Python 3, range()
xrange()
xrange()
関数はもう存在しません(Python 3ではxrange()
NameError
を発生させます)。
import timeitn = 10000def test_range(n): return for i in range(n): passdef test_xrange(n): for i in xrange(n): pass
Python 2
print 'Python', python_version()print '\ntiming range()'%timeit test_range(n)print '\n\ntiming xrange()'%timeit test_xrange(n)
Python 2.7.6timing range()1000 loops, best of 3: 433 µs per looptiming xrange()1000 loops, best of 3: 350 µs per loop
Python 3
print('Python', python_version())print('\ntiming range()')%timeit test_range(n)
Python 3.4.1timing range()1000 loops, best of 3: 520 µs per loop
print(xrange(10))
---------------------------------------------------------------------------NameError Traceback (most recent call last)<ipython-input-5-5d8f9b79ea70> in <module>()----> 1 print(xrange(10))NameError: name 'xrange' is not defined
Python3でのレンジオブジェクトの__contains__メソッド。 in Python 3
もうひとつ特筆すべきことは、range
がPython 3で「新しい」__contains__
メソッドを得たことです。xになりました(これを指摘してくれたYuchen Yingさんに感謝します)。 この __contains__
メソッドは、Python 3.x の range
で、整数型やブール型の「ルックアップ」を大幅に高速化することができます。
x = 10000000
def val_in_range(x, val): return val in range(x)
def val_in_xrange(x, val): return val in xrange(x)
となります。
print('Python', python_version())assert(val_in_range(x, x/2) == True)assert(val_in_range(x, x//2) == True)%timeit val_in_range(x, x/2)%timeit val_in_range(x, x//2)
Python 3.4.11 loops, best of 3: 742 ms per loop1000000 loops, best of 3: 1.19 µs per loop
上記のtimeit
の結果に基づいて。 の結果を見ると、「検索」の実行速度は、floatよりもinteger型の方が約60,000速くなっていることがわかります。 しかし、Python 2.xのrange
xrange
__contains__
メソッドがないので、整数型でも浮動小数点型でも「検索の速さ」はそれほど変わらないでしょう。
print 'Python', python_version()assert(val_in_xrange(x, x/2.0) == True)assert(val_in_xrange(x, x/2) == True)assert(val_in_range(x, x/2) == True)assert(val_in_range(x, x//2) == True)%timeit val_in_xrange(x, x/2.0)%timeit val_in_xrange(x, x/2)%timeit val_in_range(x, x/2.0)%timeit val_in_range(x, x/2)
Python 2.7.71 loops, best of 3: 285 ms per loop1 loops, best of 3: 179 ms per loop1 loops, best of 3: 658 ms per loop1 loops, best of 3: 556 ms per loop
以下に、__contain__
メソッドがPython 2.xに追加されていないことを示す「証明」を示します。xにはまだ追加されていません。
print('Python', python_version())range.__contains__
Python 3.4.1<slot wrapper '__contains__' of 'range' objects>
print 'Python', python_version()range.__contains__
Python 2.7.7---------------------------------------------------------------------------AttributeError Traceback (most recent call last)<ipython-input-7-05327350dafb> in <module>() 1 print 'Python', python_version()----> 2 range.__contains__AttributeError: 'builtin_function_or_method' object has no attribute '__contains__'
print 'Python', python_version()xrange.__contains__
Python 2.7.7---------------------------------------------------------------------------AttributeError Traceback (most recent call last)<ipython-input-8-7d1a71bfee8e> in <module>() 1 print 'Python', python_version()----> 2 xrange.__contains__AttributeError: type object 'xrange' has no attribute '__contains__'
Python2と3の速度差についての注意点
Python3のrange()
とPython2のxrange()
の速度差を指摘する声がありました。 これらは同じ方法で実装されているので、同じ速度を期待できるでしょう。 しかし、ここでの違いは、一般的にPython 3はPython 2よりも動作が遅い傾向にあるという事実から来ています。
def test_while(): i = 0 while i < 20000: i += 1 return
print('Python', python_version())%timeit test_while()
Python 3.4.1100 loops, best of 3: 2.68 ms per loop
div
print 'Python', python_version()%timeit test_while()
Python 2.7.61000 loops, best of 3: 1.72 ms per loop
例外の発生
Python 2が「古い」と「新しい」の両方の記法を受け入れる場合があります。
Python 2 が「古い」構文と「新しい」構文の両方の表記を受け入れるところで、Python 3 は例外の引数を括弧で囲まないと詰まってしまいます (そして順番に SyntaxError
を発生させます)。
Python 2
print 'Python', python_version()
Python 2.7.6
raise IOError, "file error"
---------------------------------------------------------------------------IOError Traceback (most recent call last)<ipython-input-8-25f049caebb0> in <module>()----> 1 raise IOError, "file error"IOError: file error
raise IOError("file error")
---------------------------------------------------------------------------IOError Traceback (most recent call last)<ipython-input-9-6f1c43f525b2> in <module>()----> 1 raise IOError("file error")IOError: file error
Python 3
print('Python', python_version())
Python 3.4.1
raise IOError, "file error"
File "<ipython-input-10-25f049caebb0>", line 1 raise IOError, "file error" ^SyntaxError: invalid syntax
Python3で例外を発生させるための正しい方法。
print('Python', python_version())raise IOError("file error")
Python 3.4.1---------------------------------------------------------------------------OSError Traceback (most recent call last)<ipython-input-11-c350544d15da> in <module>() 1 print('Python', python_version())----> 2 raise IOError("file error")OSError: file error
例外の処理
また、Python 3では例外の処理が少し変わりました。 Python 3では、”as
“キーワードを使用しなければなりません
Python 2
print 'Python', python_version()try: let_us_cause_a_NameErrorexcept NameError, err: print err, '--> our error message'
Python 2.7.6name 'let_us_cause_a_NameError' is not defined --> our error message
Python 3
print('Python', python_version())try: let_us_cause_a_NameErrorexcept NameError as err: print(err, '--> our error message')
Python 3.4.1name 'let_us_cause_a_NameError' is not defined --> our error message
div
next()
.next()
)はよく使われる機能(メソッド)ですからね。 これも特筆すべき構文変更(というか実装の変更)です。 Python 2.7.5では、functionとmethodの両方の構文が使えるところ、iv id=
はnext()
という関数がPython 3では残っているだけです(.next()
AttributeError
が発生します)。
Python 2
print 'Python', python_version()my_generator = (letter for letter in 'abcdefg')next(my_generator)my_generator.next()
Python 2.7.6'b'
Python 3
print('Python', python_version())my_generator = (letter for letter in 'abcdefg')next(my_generator)
。
Python 3.4.1'a'
my_generator.next()
---------------------------------------------------------------------------AttributeError Traceback (most recent call last)<ipython-input-14-125f388bb61b> in <module>()----> 1 my_generator.next()AttributeError: 'generator' object has no attribute 'next'
For-ループ変数とグローバル名前空間のリーク
良いニュースがあります。
これは Python 3.x で行われた変更に遡り、What’s New In Python 3.0 で以下のように説明されています:
“List comprehensions no longer support the syntactic form list()
コンストラクタ内のジェネレータ式の構文解析に近く、特にループ制御変数が周囲のスコープに漏れなくなっていることにも注意してください。”
Python 2
print 'Python', python_version()i = 1print 'before: i =', iprint 'comprehension: ', print 'after: i =', i
Python 2.7.6before: i = 1comprehension: after: i = 4
Python 3
print('Python', python_version())i = 1print('before: i =', i)print('comprehension:', )print('after: i =', i)
Python 3.4.1before: i = 1comprehension: after: i = 1
順序付けられない型を比較する
Python 3のもう一つの良い変更点は、順序付けられない型を比較しようとすると、TypeError
が警告として表示されることです。
Python 2
print 'Python', python_version()print " > 'foo' = ", > 'foo'print "(1, 2) > 'foo' = ", (1, 2) > 'foo'print " > (1, 2) = ", > (1, 2)
Python 2.7.6 > 'foo' = False(1, 2) > 'foo' = True > (1, 2) = False
Python 3
print('Python', python_version())print(" > 'foo' = ", > 'foo')print("(1, 2) > 'foo' = ", (1, 2) > 'foo')print(" > (1, 2) = ", > (1, 2))
Python 3.4.1---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-16-a9031729f4a0> in <module>() 1 print('Python', python_version())----> 2 print(" > 'foo' = ", > 'foo') 3 print("(1, 2) > 'foo' = ", (1, 2) > 'foo') 4 print(" > (1, 2) = ", > (1, 2))TypeError: unorderable types: list() > str()
input()によるユーザーの入力を解析する
残念ながら。 input()
関数はPython 3で修正され、ユーザーの入力を常にstr
オブジェクトとして保存するようになりました。 Python 2では、strings
raw_input()
を使用しなければなりません。
Python 2
Python 2.7.6 on darwinType "help", "copyright", "credit" or "license "で詳細を確認できます。>>> my_input = input('enter a number: ')数字を入力してください。 123>>> type(my_input)<type 'int'>>>> my_input = raw_input('enter a number: ')数字を入力してください。 123>>> type(my_input)<type 'str'>
Python 3
Python 3.4.1 on darwin "help", "copyright", "credit", "license "を入力すると、より詳しい情報が得られます。>>> my_input = input('enter a number: ')数字を入力してください。 123>>> type(my_input)< class 'str'>
リストではなく反復可能なオブジェクトを返す
すでにxrange
のセクションで見たように、いくつかの関数やメソッドは反復可能なオブジェクトを返します。 いくつかの関数やメソッドは、Python 2 のリストではなく、Python 3 では反復可能なオブジェクトを返します。
通常、これらのオブジェクトは一度だけ繰り返し処理されるので、この変更はメモリを節約するために非常に意味があると思います。
また、list
list()
list
に変換するだけです。
Python 2
print 'Python', python_version()print range(3)print type(range(3))
Python 2.7.6<type 'list'>
Python 3
print('Python', python_version())print(range(3))print(type(range(3)))print(list(range(3)))
Python 3.4.1range(0, 3)<class 'range'>
Python 3ではリストを返さなくなった、よく使われる関数やメソッドをご紹介します。
-
zip()
-
map()
-
filter()
-
dictionary の
.keys()
メソッド -
dictionary の
.values()
メソッド -
dictionary の
.items()
メソッド
Bankerの丸め
Python 3では、最後の有効数字が同点(…5)になったときに小数を丸めるという、今では標準的な方法を採用しました。5) を採用しました。 現在、Python 3では、小数は最も近い偶数に丸められます。 コードの移植性には不都合がありますが、大きな数字への偏りを避けることができるため、切り上げに比べてより良い丸め方だと思われます。 詳細については、優れた Wikipedia の記事と段落を参照してください。
- https://en.wikipedia.org/wiki/Rounding#Round_half_to_even
- https://en.wikipedia.org/wiki/IEEE_floating_point#Roundings_to_nearest
Python 2
print 'Python', python_version()
Python 2.7.12
round(15.5)
16.0
round(16.5)
17.0
Python 3
print('Python', python_version())
Python 3.5.1
round(15.5)
16
round(16.5)
16
More articles about Python 2 and Python 3
ここでは、Python 2とPython 3に関する記事の中で、フォローアップとしておすすめしたい記事を紹介します。を紹介します。
//Python 3へのポーティング
-
自分の開発活動にPython 2とPython 3のどちらを使うべきか
-
What’s New In Python 3.0
-
Python 3への移植
-
Python 2コードのPython 3への移植
-
How keep Python
//Pro and anti Python 3
-
Python 3へのアップグレードを拒否したために使用できないPythonの10の素晴らしい機能。 なぜなら、あなたは Python 3 へのアップグレードを拒否しているからです
-
Python 3 の Unicode について知りたくなかったことすべて
-
Python 3 は Python を殺している
-
Python 3 は Python を復活させることができる
-
Python 3 は大丈夫