サーチ…


前書き

ほとんどの言語とは異なり、Pythonは2つのメジャーバージョンをサポートしています。 Python 3がリリースされた2008年以来、多くの人が移行を行いましたが、多くはそうしていませんでした。両方を理解するために、このセクションではPython 2とPython 3の重要な違いについて説明します。

備考

現在サポートされているPythonのバージョンは2.7(Python 2)と3.6(Python 3)です。さらに、バージョン3.3および3.4​​は、ソース形式でセキュリティ更新プログラムを受信します。

Python 2.7はほとんどの旧バージョンのPythonと下位互換性があり、Pythonのほとんどの1.xおよび2.xバージョンのPythonコードを変更せずに実行できます。これは広範囲に利用可能であり、広範なパッケージを集めています。また、CPython開発者は非推奨と見なされ、セキュリティとバグ修正の開発のみを受け取ります。 CPythonの開発者は、このバージョンの言語を2020年に放棄しようとしています。

Python Enhancement Proposal 373によれば、2016年6月25日以降、Python 2の将来のリリースは予定されていませんが、2020年まではバグ修正やセキュリティアップデートがサポートされます。(2020年の正確な日付はPythonの2)

Python 3は、言語開発者が言語の核心にあった懸念に対処するために意図的に下位互換性を破った。 Python 3は新しい開発と新機能を受け取ります。これは、言語開発者が前進する予定の言語のバージョンです。

Python 3.0の初期リリースから現在のバージョンまでの間に、Python 3のいくつかの機能はPython 2.6にバックポートされ、Python 3の他の部分はPython 2との構文互換性が拡張されました。したがって、 Python 2とPython 3の両方で、将来のインポートと特別なモジュール( 6のような)を使って動作するPython。

将来のインポートは、モジュールの始めにある必要があります。

from __future__ import print_function
# other imports and instructions go after __future__
print('Hello world')

__future__モジュールの詳細については、Pythonドキュメントの関連ページを参照してください

2to3ツールは、Python 2.xコードをPython 3.xコードに変換するPythonプログラムですPythonのドキュメントも参照してください)。

パッケージ6はPython 2/3との互換性のためのユーティリティを提供します:

  • 名前を変更したライブラリへの統一されたアクセス
  • 文字列/ユニコードタイプの変数
  • 削除されたメソッドまたは名前が変更されたメソッドの関数

Python 2とPython 3の相違点については、ここで参照できます

印刷ステートメントと印刷機能

Python 2では、 printはステートメントです:

Python 2.x 2.7
print "Hello World"
print                         # print a newline
print "No newline",           # add trailing comma to remove newline 
print >>sys.stderr, "Error"   # print to stderr
print("hello")                # print "hello", since ("hello") == "hello"
print()                       # print an empty tuple "()"
print 1, 2, 3                 # print space-separated arguments: "1 2 3"
print(1, 2, 3)                # print tuple "(1, 2, 3)"

Python 3では、 print()は汎用のキーワード引数を持つ関数です:

Python 3.x 3.0
print "Hello World"              # SyntaxError
print("Hello World")
print()                          # print a newline (must use parentheses)
print("No newline", end="")      # end specifies what to append (defaults to newline)
print("Error", file=sys.stderr)  # file specifies the output buffer
print("Comma", "separated", "output", sep=",")  # sep specifies the separator
print("A", "B", "C", sep="")     # null string for sep: prints as ABC
print("Flush this", flush=True)  # flush the output buffer, added in Python 3.3
print(1, 2, 3)                   # print space-separated arguments: "1 2 3"
print((1, 2, 3))                 # print tuple "(1, 2, 3)"

印刷機能には、次のパラメータがあります。

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

sepは、渡すオブジェクトを区切って印刷するものです。例えば:

print('foo', 'bar', sep='~') # out: foo~bar
print('foo', 'bar', sep='.') # out: foo.bar

endはprintステートメントの終わりの後に続くものです。例えば:

print('foo', 'bar', end='!') # out: foo bar!

同じ行に印刷されます print文を終了する非改行、次の再印刷:

print('foo', end='~')
print('bar')
# out: foo~bar

注意:将来の互換性のために、 print 機能はPython 2.6以降でも利用できます。ただし、 print ステートメントの解析が無効にされていない限り使用することはできません

from __future__ import print_function

この関数は、 flushパラメータがない点を除いて、Python 3とまったく同じ形式です。

根拠については、PEP 3105を参照してください。

文字列:バイトとUnicode

Python 2.x 2.7

Python 2には、文字列型( str )のバイトとstrのテキスト( unicode )からなる2種類の文字列があります。

Python 2では、 str型のオブジェクトは常にバイトシーケンスですが、テキストデータとバイナリデータの両方によく使用されます。

文字列リテラルはバイト文字列として解釈されます。

s = 'Cafe'    # type(s) == str

2つの例外があります。Unicode(text)リテラルを明示的に定義するには、リテラルにu

s = u'Café'   # type(s) == unicode
b = 'Lorem ipsum'  # type(b) == str

あるいは、モジュール全体の文字列リテラルがUnicode(テキスト)リテラルを作成するように指定することもできます。

from __future__ import unicode_literals

s = 'Café'   # type(s) == unicode
b = 'Lorem ipsum'  # type(b) == unicode

変数が文字列(Unicodeかバイト文字列)かどうかを確認するには、次のようにします:

isinstance(s, basestring)
Python 3.x 3.0

Python 3では、 str型はUnicodeテキスト型です。

s = 'Cafe'           # type(s) == str
s = 'Café'           # type(s) == str (note the accented trailing e)

さらに、Python 3では、バイナリの「ブロブ」やエンコードに依存しないファイルへの書き込みに適したbytesオブジェクトが追加されました。バイトオブジェクトを作成するには、 bを文字列リテラルに接頭するか、文字列のencodeメソッドを呼び出します。

# Or, if you really need a byte string:
s = b'Cafe'          # type(s) == bytes
s = 'Café'.encode()  # type(s) == bytes

値が文字列かどうかをテストするには、次のようにします。

isinstance(s, str)
Python 3.x 3.3

Python 2とPython 3のコードベース間の互換性を容易にするために、文字列リテラルに接頭辞u付けることもできます。 Python 3では、すべての文字列がデフォルトでUnicodeなので、文字列リテラルの前にuても効果はありません。

u'Cafe' == 'Cafe'

Python 2の生のUnicode文字列の接頭辞urはサポートされていません。

>>> ur'Café'
  File "<stdin>", line 1
    ur'Café'
           ^
SyntaxError: invalid syntax

Python 3 text( str )オブジェクトをencode 、そのテキストのbytes表現に変換する必要があることに注意してください。このメソッドのデフォルトのエンコーディングはUTF-8です。

decodeを使ってbytesオブジェクトに、それが表すUnicodeテキストを尋ねることができます:

>>> b.decode()
'Café'
Python 2.x 2.6

bytesタイプはPython 2と3の両方に存在しbytesが、 unicode型はPython 2にのみ存在します。Python 2でPython 3の暗黙のUnicode文字列を使用するには、コードファイルの先頭に次のコードを追加します。

from __future__ import unicode_literals
print(repr("hi"))
# u'hi'
Python 3.x 3.0

もう1つの重要な違いは、Python 3のインデックスバイトがint出力になることです。

b"abc"[0] == 97

1のサイズでスライスすると、長さが1バイトのオブジェクトになります。

b"abc"[0:1] == b"a"

さらに、Python 3はユニコードでいくつかの異常な動作修正します。つまり、Python 2でバイト文字列を反転します。たとえば、 次の問題が解決されました。

# -*- coding: utf8 -*-
print("Hi, my name is Łukasz Langa.")
print(u"Hi, my name is Łukasz Langa."[::-1])
print("Hi, my name is Łukasz Langa."[::-1])

# Output in Python 2
# Hi, my name is Łukasz Langa.
# .agnaL zsakuŁ si eman ym ,iH
# .agnaL zsaku�� si eman ym ,iH

# Output in Python 3
# Hi, my name is Łukasz Langa.
# .agnaL zsakuŁ si eman ym ,iH
# .agnaL zsakuŁ si eman ym ,iH

整数部

標準除算記号/ )は、整数に適用すると、Python 3とPython 2では動作が異なります。

Python 3で整数を別の整数で割ると、除算演算x / y真の除算を表し( __truediv__メソッドを使用)、浮動小数点の結果を生成します。一方、パイソン2における同様の動作を表す古典的な分割 (また床を取るとしても知られる)負の無限大に向かってダウン結果を丸めます。

例えば:

コード Python 2の出力 Python 3の出力
3 / 2 1 1.5
2 / 3 0 0.6666666666666666
-3 / 2 -2 -1.5

ゼロへの丸めの振る舞いは、 Python 2.2では廃止されましたが、後方互換性のためにPython 2.7に残っており、Python 3では削除されています。

注意: Python 2で浮動小数点の結果を得るには(フロアの丸めなし)、オペランドの1つを小数点で指定します。上記のPython 2で0を与える2/3例は、 2 / 3.0または2.0 / 3または2.0/3.0として使用され、 0.6666666666666666

コード Python 2の出力 Python 3の出力
3.0 / 2.0 1.5 1.5
2 / 3.0 0.6666666666666666 0.6666666666666666
-3.0 / 2 -1.5 -1.5

フロア分割演算子// )もあり、両方のバージョンで同じように動作します。最も近い整数に切り下げられます。 (浮動小数点で使用すると浮動小数点が返されますが)どちらのバージョンでも、 //演算子は__floordiv__マップされ__floordiv__

コード Python 2の出力 Python 3の出力
3 // 2 1 1
2 // 3 0 0
-3 // 2 -2 -2
3.0 // 2.0 1.0 1.0
2.0 // 3 0.0 0.0
-3 // 2.0 -2.0 -2.0

operatorモジュール内のネイティブ関数を使用して、真の除算またはフロア除算を明示的に実行することができます。

from operator import truediv, floordiv
assert truediv(10, 8) == 1.25            # equivalent to `/` in Python 3
assert floordiv(10, 8) == 1              # equivalent to `//`

明確で明示的ですが、すべての部門で演算子関数を使用するのは面倒です。 /演算子の動作を変更する方が望ましいことが多い。一般的な方法はfrom __future__ import divisionを各モジュールの最初のステートメントとして追加することによって、典型的な除算の振る舞いを排除することです。

# needs to be the first statement in a module
from __future__ import division
コード Python 2の出力 Python 3の出力
3 / 2 1.5 1.5
2 / 3 0.6666666666666666 0.6666666666666666
-3 / 2 -1.5 -1.5

from __future__ import divisionは、 /演算子が__future__ importを含むモジュール内でのみ真の除算を表していることを保証するので、すべての新しいモジュールでそれを有効にしない魅力的な理由はありません。

:他のいくつかのプログラミング言語は、Pythonが負の無限大の方向に丸めるのではなく、 ゼロに切り捨てる(truncation)ようにします(つまり、それらの言語では-3 / 2 == -1 )。この動作は、コードの移植または比較時に混乱を招く可能性があります。


浮動小数点型のオペランドに関する注意from __future__ import division代わりに、通常の除算シンボル/を使用し、オペランドの少なくとも1つがfloat: 3 / 2.0 == 1.5ことを確認することができます。しかし、これは悪い習慣とみなすことができます。 average = sum(items) / len(items)を書いてfloatに引数の1つをキャストするのを忘れるのは簡単です。あなたが入った配列でテストする場合はさらに、このようなケースはしばしば、例えば、テスト中に通知を回避するfloat秒が、配列受け取るint生産で秒。さらに、同じコードがPython 3で使用されている場合、 3 / 2 == 1がTrueであると予想されるプログラムは正しく動作しません。

除算演算子がPython 3で変更された理由と古いスタイルの除算を避ける理由については、 PEP 238を参照してください。


除算の詳細については、「 単純な数学」のトピックを参照してください。

Reduceはもはやビルトインではありません

Python 2では、 reduceは組み込み関数またはfunctoolsパッケージ(バージョン2.6以降)から利用できますが、Python 3ではreducefunctoolsからのみ利用できます。ただしの構文reduce Python2とのpython3の両方では同じであり、であるreduce(function_to_reduce, list_to_reduce)

一例として、隣接する数値のそれぞれを分割することによってリストを単一の値に減らすことを考えてみましょう。ここでは、 operatorライブラリの関数truedivを使用します。

Python 2.xでは以下のように簡単です:

Python 2.x 2.3
>>> my_list = [1, 2, 3, 4, 5]
>>> import operator
>>> reduce(operator.truediv, my_list)
0.008333333333333333

Python 3.xでは、この例は少し複雑になりました。

Python 3.x 3.0
>>> my_list = [1, 2, 3, 4, 5]
>>> import operator, functools
>>> functools.reduce(operator.truediv, my_list)
0.008333333333333333

またfrom functools import reduceを使用from functools import reduceて、名前空間名でreduceを呼び出さないようにreduceこともできます。

範囲関数とxrange関数の違い

Python 2では、 range関数はリストを返しますが、 xrangeは特殊なxrangeオブジェクトを作成します。これは他の組み込みシーケンス型と異なり、スライシングをサポートせず、 indexメソッドもcountメソッドもありません。

Python 2.x 2.3
print(range(1, 10))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

print(isinstance(range(1, 10), list))
# Out: True

print(xrange(1, 10))
# Out: xrange(1, 10)

print(isinstance(xrange(1, 10), xrange))
# Out: True

Python 3では、 xrangerangeシーケンスに展開され、 rangeオブジェクトが作成されました。 xrangeタイプはありません:

Python 3.x 3.0
print(range(1, 10))
# Out: range(1, 10)

print(isinstance(range(1, 10), range))
# Out: True

# print(xrange(1, 10))
# The output will be:
#Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#NameError: name 'xrange' is not defined

さらに、Python 3.2以降、 rangeはスライシング、 index 、およびcountもサポートしていcount

print(range(1, 10)[3:7])
# Out: range(3, 7)
print(range(1, 10).count(5))
# Out: 1
print(range(1, 10).index(7))
# Out: 6

リストの代わりに特殊なシーケンス型を使用する利点は、インタプリタがリストのメモリを割り当てて、それを移入する必要がないことです。

Python 2.x 2.3
# range(10000000000000000)
# The output would be:
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# MemoryError

print(xrange(100000000000000000))
# Out: xrange(100000000000000000)

後者の動作は一般的には望ましいので、Python 3では前者が削除されました。Python 3でリストを作成したい場合は、 rangeオブジェクトでlist()コンストラクタを使うだけです:

Python 3.x 3.0
print(list(range(1, 10)))
# Out: [1, 2, 3, 4, 5, 6, 7, 8, 9]

互換性

Python 2.xとPython 3.xの両方のバージョン間の互換性を維持するために、 futureの外部パッケージからbuiltinsモジュールを使用して、 前方互換性後方 互換性の両方を達成することができます。

Python 2.x 2.0
#forward-compatible
from builtins import range

for i in range(10**8):
    pass
Python 3.x 3.0
#backward-compatible
from past.builtins import xrange

for i in xrange(10**8):
    pass

futureライブラリのrangeは、Python 3.2以降の組み込みメソッドと同様に、すべてのPythonバージョンでスライス、 index 、およびcountサポートしています。

イテラブルの開梱

Python 3.x 3.0

Python 3では、反復可能な要素の正確な数を知らずに反復可能なものをアンパックすることができ、反復可能な変数の終わりを保持する変数を持つことさえできます。そのために、値のリストを収集する変数を指定します。これは、名前の前にアスタリスクを置くことによって行われます。たとえば、 listアンパック:

first, second, *tail, last = [1, 2, 3, 4, 5]
print(first)
# Out: 1
print(second)
# Out: 2
print(tail)
# Out: [3, 4]
print(last)
# Out: 5

*variable構文を使用する場合、元のタイプがリストでなくても、 variableは常にリストになります。元のリストの要素の数に応じて、0個以上の要素を含むことがあります。

first, second, *tail, last = [1, 2, 3, 4]
print(tail)
# Out: [3]

first, second, *tail, last = [1, 2, 3]
print(tail)
# Out: []
print(last)
# Out: 3

同様に、 str

begin, *tail = "Hello"
print(begin)
# Out: 'H'
print(tail)
# Out: ['e', 'l', 'l', 'o']

dateのアンパックの例。 _は、この例では使い捨て変数として使用されています(私たちはyear値だけに興味があります):

person = ('John', 'Doe', (10, 16, 2016))
*_, (*_, year_of_birth) = person
print(year_of_birth)
# Out: 2016

*は可変個数のアイテムを食べるので、割り当て内で同じiterableに対して 2つの*持つことはできません - 最初のアンパックに入る要素の数と2番目のアンパックの数は分かりません:

*head, *tail = [1, 2]
# Out: SyntaxError: two starred expressions in assignment
Python 3.x 3.5

これまでは、割り当ての解凍について議論しました。 ***Python 3.5で拡張されました 。 1つの式で複数のアンパック操作を行うことが可能になりました。

{*range(4), 4, *(5, 6, 7)}
# Out: {0, 1, 2, 3, 4, 5, 6, 7}
Python 2.x 2.0

iterableを関数の引数に展開することも可能です:

iterable = [1, 2, 3, 4, 5]
print(iterable)
# Out: [1, 2, 3, 4, 5]
print(*iterable)
# Out: 1 2 3 4 5
Python 3.x 3.5

辞書を展開すると、隣接する2つの星**使用されます( PEP 448 )。

tail = {'y': 2, 'z': 3}
{'x': 1, **tail}
 # Out: {'x': 1, 'y': 2, 'z': 3}

これにより、古い値を上書きして辞書をマージすることができます。

dict1 = {'x': 1, 'y': 1}
dict2 = {'y': 2, 'z': 3}
{**dict1, **dict2}
# Out: {'x': 1, 'y': 2, 'z': 3}
Python 3.x 3.0

Python 3は、関数内のタプルのアンパックを削除しました。したがって、以下はPython 3では動作しません

# Works in Python 2, but syntax error in Python 3:
map(lambda (x, y): x + y, zip(range(5), range(5)))
# Same is true for non-lambdas:
def example((x, y)):
    pass

# Works in both Python 2 and Python 3:
map(lambda x: x[0] + x[1], zip(range(5), range(5)))
# And non-lambdas, too:
def working_example(x_y):
    x, y = x_y
    pass

詳細な根拠については、PEP 3113を参照してください。

例外の発生と処理

これは、Pythonの2構文で、カンマに注意し,上のraise及びexceptラインを:

Python 2.x 2.3
try:
    raise IOError, "input/output error"
except IOError, exc:
    print exc

Python 3では,構文が削除され、かっことasキーワードで置き換えられます。

try:
    raise IOError("input/output error")
except IOError as exc:
    print(exc)

下位互換性を保つために、Python 3以降の構文でもPython 3の構文を利用できるため、以前のバージョンと互換性がある必要のないすべての新しいコードに使用する必要があります。


Python 3.x 3.0

Python 3では、 例外の連鎖も追加されています 。そこで、この例外の原因が他のいくつかの例外であることを伝えることができます。例えば

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}') from e

except文で発生する例外はDatabaseError型ですが、元の例外はその例外の__cause__属性としてマークされています。トレースバックが表示されると、元の例外もトレースバックに表示されます。

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')

明示的な連鎖をせずexceptブロックを投げた場合:

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}')

トレースバックは

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
FileNotFoundError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')
Python 2.x 2.0

どちらもPython 2.xではサポートされていません。 exceptブロックで別の例外が発生した場合、元の例外とそのトレースバックは失われます。互換性のために次のコードを使用できます。

import sys
import traceback

try:
    funcWithError()
except:
    sys_vers = getattr(sys, 'version_info', (0,))
    if sys_vers < (3, 0):
        traceback.print_exc()
    raise Exception("new exception")
Python 3.x 3.3

以前にスローされた例外を "忘れる"には、 raise from None使用します。

try:
    file = open('database.db')
except FileNotFoundError as e:
    raise DatabaseError('Cannot open {}') from None

トレースバックは単純に

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
DatabaseError('Cannot open database.db')

または、Python 2と3の両方と互換性を持たせるには、次のように6つのパッケージを使用します:

import six
try:
    file = open('database.db')
except FileNotFoundError as e:
    six.raise_from(DatabaseError('Cannot open {}'), None)

イテレータの.next()メソッドの名前が変更されました

Python 2では、イテレータ自体でnextというメソッドを使用して、イテレータをトラバースすることができます。

Python 2.x 2.3
g = (i for i in range(0, 3))
g.next()  # Yields 0
g.next()  # Yields 1
g.next()  # Yields 2

Python 3では、 .nextメソッドの名前が.__next__に変更され、 "magic"ロールとして.nextされます。したがって、 .nextを呼び出すとAttributeErrorます。 Python 2とPython 3の両方でこの機能にアクセスする正しい方法は、イテレータを引数としてnext 関数を呼び出すことです。

Python 3.x 3.0
g = (i for i in range(0, 3))
next(g)  # Yields 0
next(g)  # Yields 1
next(g)  # Yields 2

このコードは、2.6から現在のリリースまでのバージョン間で移植可能です。

異なるタイプの比較

Python 2.x 2.3

異なるタイプのオブジェクトを比較することができます。結果は任意ですが一貫しています。それらは、 Noneが他よりも少なく、数値型が非数値型よりも小さく、その他すべてが型によって辞書順に並べられるように順序付けられます。したがって、 intstrより小さく、 tuplelistよりも大きい:

[1, 2] > 'foo'
# Out: False
(1, 2) > 'foo'
# Out: True
[1, 2] > (1, 2)
# Out: False
100 < [1, 'x'] < 'xyz' < (1, 'x')
# Out: True

これはもともとは、混合型のリストをソートすることができ、オブジェクトを型ごとにグループ化するために行われました。

l = [7, 'x', (1, 2), [5, 6], 5, 8.0, 'y', 1.2, [7, 8], 'z']
sorted(l)
# Out: [1.2, 5, 7, 8.0, [5, 6], [7, 8], 'x', 'y', 'z', (1, 2)]
Python 3.x 3.0

異なる(数値以外の)型を比較す​​るときに例外が発生します。

1 < 1.5
# Out: True

[1, 2] > 'foo'
# TypeError: unorderable types: list() > str()
(1, 2) > 'foo'
# TypeError: unorderable types: tuple() > str()
[1, 2] > (1, 2)
# TypeError: unorderable types: list() > tuple()

Python 3で混合リストを型別にソートし、バージョン間の互換性を実現するには、ソートされた関数にキーを提供する必要があります。

>>> list = [1, 'hello', [3, 4], {'python': 2}, 'stackoverflow', 8, {'python': 3}, [5, 6]]
>>> sorted(list, key=str)
# Out: [1, 8, [3, 4], [5, 6], 'hello', 'stackoverflow', {'python': 2}, {'python': 3}]

key関数としてstrを使用すると、比較の目的でのみ各項目が一時的に文字列に変換されます。それから、 ['{ 0-9いずれかで始まる文字列表現を見ると、それらの文字列をすべてソートすることができます。

ユーザー入力

Python 2では、 raw_input関数を使用してユーザー入力を受け入れ、

Python 2.x 2.3
user_input = raw_input()

Python 3では、 input関数を使用してユーザー入力を受け入れます。

Python 3.x 3.0
user_input = input()

Python 2では、 input関数は入力を受け入れて解釈します。これは便利ですが、いくつかのセキュリティ上の考慮事項があり、Python 3では削除されました。同じ機能にアクセスするには、 eval(input())を使用できます。

スクリプトを2つのバージョン間で移植可能にするには、以下のコードをPythonスクリプトの最上部の近くに置くことができます。

try:
    input = raw_input
except NameError:
    pass

ディクショナリ方式の変更

Python 3では、辞書メソッドの多くはPython 2とはかなり違っていて、多くは削除されています: has_keyiter*view*はなくなりました。長い間廃止されていたd.has_key(key)代わりにkey in d使用する必要があります。

Python 2では、辞書のメソッドのkeysvalues 、およびitemsはリストを返します。 Python 3では、代わりにビューオブジェクトを返します 。ビュー・オブジェクトはイテレータではなく、次の2つの点で異なります。

  • 彼らはサイズを持っています(1つはlen関数を使うことができます)
  • 彼らは何度も繰り返すことができます

さらに、イテレータと同様に、ディクショナリの変更はビュー・オブジェクトに反映されます。

Python 2.7は、これらのメソッドをPython 3からバックポートしました。 viewkeysviewvalues viewkeysviewvaluesとして利用できviewitems 。 Python 2コードをPython 3コードに変換するには、対応するフォームを以下のようにします。

  • Python 2のd.keys()d.values()d.items()list(d.keys())list(d.values())list(d.items())
  • d.iterkeys()d.itervalues()およびd.iteritems()iter(d.keys())に変更するか、 iter(d)変更する必要があります。 iter(d.values())およびiter(d.items())それぞれ
  • そして最終的にはPython 2.7メソッド呼び出しd.viewkeys()d.viewvalues()d.viewitems()で置き換えることができるd.keys() d.values()d.items()

Python 2のコードを移植することは、辞書のキー、値、または項目を反復処理しながらそれを変更することは時々難しいことがあります。検討してください:

d = {'a': 0, 'b': 1, 'c': 2, '!': 3}
for key in d.keys():
    if key.isalpha():
        del d[key]

コードはPython 3でも同様に動作しkeysが、 keysメソッドはリストではなくビューオブジェクトを返します。繰り返し処理中に辞書のサイズが変更されると、Python 3のコードはRuntimeError: dictionary changed size during iterationクラッシュしRuntimeError: dictionary changed size during iteration 。もちろん、解決策はfor key in list(d)を正しく書き込むことfor key in list(d)

同様に、ビュー・オブジェクトはイテレータとは異なる動作をします。つまり、 next()オブジェクトを使用することはできず反復処理を再開することはできません。代わりに再起動します。 Python 2のコードがd.iterkeys()d.itervalues()またはd.iteritems()の戻り値を、 iterableの代わりにiteratorを必要とするメソッドにd.iteritems()場合、 iter(d)iter(d.values()) Python 3ではiter(d.values())またはiter(d.items())します。

exec文はPython 3の関数です

Python 2では、 execは特別な構文を持つ文です: exec code [in globals[, locals]]. Python 3では、 execは関数exec(code, [, globals[, locals]])になり、Python 2の構文はSyntaxErrorます。

printがstatementから関数に変更されたときに、 __future__ importも追加されました。しかし、 from __future__ import exec_functionは必要ありませんfrom __future__ import exec_function 2のexec文は、Python 3のexec関数の呼び出しとまったく同じ構文で使用することもできます。

Python 2.x 2.3
exec 'code'
exec 'code' in global_vars
exec 'code' in global_vars, local_vars

フォームに

Python 3.x 3.0
exec('code')
exec('code', global_vars)
exec('code', global_vars, local_vars)

後者の形式は、Python 2とPython 3の両方で同じように動作することが保証されています。

Python 2のhasattr関数のバグ

Python 2では、プロパティがエラーを発生させると、 hasattrはこのプロパティを無視してFalse返します。

class A(object):
    @property
    def get(self):
        raise IOError


class B(object):
    @property
    def get(self):
        return 'get in b'

a = A()
b = B()

print 'a hasattr get: ', hasattr(a, 'get')
# output False in Python 2 (fixed, True in Python 3)
print 'b hasattr get', hasattr(b, 'get')
# output True in Python 2 and Python 3

このバグはPython3で修正されています。したがって、Python 2を使用する場合は、

try:
    a.get
except AttributeError:
    print("no get property!")

代わりにgetattr使用してください

p = getattr(a, "get", None)
if p is not None:
    print(p)
else:
    print("no get property!")

モジュール名の変更

標準ライブラリのいくつかのモジュールの名前が変更されました:

旧名新しい名前
_winreg ウィグレッグ
ConfigParser configparser
copy_reg コピーレッグ
キューキュー
SocketServer ソケットサーバー
_markupbase マークアップベース
repr reprlib
test.test_support test.support
Tkinter トキンター
tkFileDialog tkinter.filedialog
urllib / urllib2 urllib、urllib.parse、urllib.error、urllib.response、urllib.request、urllib.robotparser

一部のモジュールは、ファイルからライブラリに変換さえさえあります。例として上からtkinterとurllibを取ってください。

互換性

Python 2.xと3.xの両方のバージョン間の互換性を維持する場合、 future外部パッケージを使用して、Python 2.xバージョンでPython 3.xの名前を持つトップレベルの標準ライブラリパッケージをインポートすることができます。

オクタル定数

Python 2では、8進数のリテラルは次のように定義できます。

>>> 0755  # only Python 2

相互互換性を保証するには、

0o755  # both Python 2 and Python 3

すべてのクラスは、Python 3では「新しいスタイルのクラス」です。

Python 3.xすべてのクラスは新しいスタイルのクラスです。新しいクラスを定義するとき、Pythonは暗黙的にobjectから継承しobject 。そのため、 class定義でobjectを指定するobjectは完全にオプションです。

Python 3.x 3.0
class X: pass
class Y(object): pass

これらのクラスはどちらも、 objectmro (メソッド解決順序)にmro object

Python 3.x 3.0
>>> X.__mro__
(__main__.X, object)

>>> Y.__mro__
(__main__.Y, object)

Python 2.xクラスは、デフォルトで古いスタイルのクラスです。彼らは暗黙のうちにobjectから継承しません。これにより、基本classとしてobjectを明示的に追加するかどうかによって、クラスのセマンティクスが異なります。

Python 2.x 2.3
class X: pass
class Y(object): pass

この場合、 Y__mro__を出力しようとすると、Python 3.x場合と同様の出力が表示されます:

Python 2.x 2.3
>>> Y.__mro__
(<class '__main__.Y'>, <type 'object'>)

これは、明示的にYをオブジェクトから継承させるために、 class Y(object): pass定義するために発生します。オブジェクトから継承しないクラスX場合、 __mro__属性は存在しません。アクセスしようとするとAttributeErrorます。

両方のPythonバージョン間の互換性保証するために、 objectを基本クラスとしてクラスを定義することができます。

class mycls(object):
    """I am fully compatible with Python 2/3"""

あるいは、 __metaclass__変数がグローバルスコープでtypeに設定されている場合、 __metaclass__されたモジュール内で後で定義されるすべてのクラスは、 objectから明示的に継承する必要がなく暗黙のうちに新しいスタイルになりobject

__metaclass__ = type

class mycls:
    """I am also fully compatible with Python 2/3"""

削除された演算子<>と! `は、!=とrepr()と同義です。

Python 2では、 <>!=同義語です。同様に、 `foo`repr(foo)同義語です。

Python 2.x 2.7
>>> 1 <> 2
True
>>> 1 <> 1
False
>>> foo = 'hello world'
>>> repr(foo)
"'hello world'"
>>> `foo`
"'hello world'"
Python 3.x 3.0
>>> 1 <> 2
  File "<stdin>", line 1
    1 <> 2
       ^
SyntaxError: invalid syntax
>>> `foo`
  File "<stdin>", line 1
    `foo`
    ^
SyntaxError: invalid syntax

もはや利用可能な16進数へのエンコード/デコード

Python 2.x 2.7
"1deadbeef3".decode('hex')
# Out: '\x1d\xea\xdb\xee\xf3'
'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Out: 1deadbeef3
Python 3.x 3.0
"1deadbeef3".decode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# AttributeError: 'str' object has no attribute 'decode'

b"1deadbeef3".decode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# LookupError: 'hex' is not a text encoding; use codecs.decode() to handle arbitrary codecs

'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs

b'\x1d\xea\xdb\xee\xf3'.encode('hex')
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# AttributeError: 'bytes' object has no attribute 'encode'

ただし、エラーメッセージで示唆されるように、 codecsモジュールを使用して同じ結果を得ることができます。

import codecs
codecs.decode('1deadbeef4', 'hex')
# Out: b'\x1d\xea\xdb\xee\xf4'
codecs.encode(b'\x1d\xea\xdb\xee\xf4', 'hex')
# Out: b'1deadbeef4'

codecs.encodebytesオブジェクトを返します。 ASCIIにdecodeするstrオブジェクトを取得するには:

codecs.encode(b'\x1d\xea\xdb\xee\xff', 'hex').decode('ascii')
# Out: '1deadbeeff'

Python 3でcmp関数が削除されました

Python 3では、 cmp組み込み関数が__cmp__特殊メソッドとともに削除されました。

ドキュメントから:

cmp()関数は__cmp__()として扱われ、 __cmp__()特殊メソッドはサポートされなくなりました。ソートには__eq__()__hash__()__lt__()を使用し、必要に応じて他の豊富な比較を使用します。 (実際にcmp()機能が必要な場合は、式(a > b) - (a < b)cmp(a, b)同等物として使用できます。

さらに、 cmpパラメーターを受け入れた組み込み関数はすべて、 keyキーワードのみのパラメーターを受け入れるようになりました。

functoolsモジュールにも便利な機能がありcmp_to_key(func)あなたから変換することができcmpにスタイルのファンクションkeyスタイルの機能:

古いスタイルの比較関数をキー関数に変換します。キー機能( sorted()min()max()heapq.nlargest()heapq.nsmallest()itertools.groupby() )を受け付けるツールで使用されます。この関数は主に、比較関数の使用をサポートするPython 2から変換されるプログラムの遷移ツールとして使用されます。

リストの理解における漏れ変数

Python 2.x 2.3
x = 'hello world!'
vowels = [x for x in 'AEIOU'] 

print (vowels)
# Out: ['A', 'E', 'I', 'O', 'U']
print(x)
# Out: 'U'   
Python 3.x 3.0
x = 'hello world!'
vowels = [x for x in 'AEIOU']

print (vowels)
# Out: ['A', 'E', 'I', 'O', 'U']
print(x)
# Out: 'hello world!'

この例からわかるように、Python 2ではxの値が漏れました。それはhello world!マスクしましたhello world!これはループが終了したときのxの最後の値だったので、 U出力します。

しかし、Python 3 xでは、最初に定義されたhello world!プリントされhello world!リスト内包表記のローカル変数は、周囲のスコープの変数をマスクしないためです。

さらに、ジェネレータ表現(Python 2.5以降で利用可能)や、辞書や集合の補完(Python 3からPython 2.7にバックポートされた)はPython 2で変数をリークしません。

Python 2とPython 3の両方で、forループを使用すると、変数が周囲のスコープに漏れることに注意してください。

x = 'hello world!'
vowels = []
for x in 'AEIOU':
    vowels.append(x)
print(x)
# Out: 'U'

地図()

map()は、iterableの要素に関数を適用するのに便利な組み込み関数です。 Python 2では、 mapはリストを返します。 Python 3では、 mapはジェネレータであるマップオブジェクトを返します。

# Python 2.X
>>> map(str, [1, 2, 3, 4, 5])
['1', '2', '3', '4', '5']
>>> type(_)
>>> <class 'list'>

# Python 3.X
>>> map(str, [1, 2, 3, 4, 5])
<map object at 0x*>
>>> type(_)
<class 'map'>

# We need to apply map again because we "consumed" the previous map....
>>> map(str, [1, 2, 3, 4, 5])
>>> list(_)
['1', '2', '3', '4', '5']

Python 2では、 Noneを渡してID関数として機能させることができます。これはもはやPython 3では機能しません。

Python 2.x 2.3
>>> map(None, [0, 1, 2, 3, 0, 4])
[0, 1, 2, 3, 0, 4]
Python 3.x 3.0
>>> list(map(None, [0, 1, 2, 3, 0, 5]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

さらに、Python 2で引数として複数のiterableを渡す場合、 mapは短いiterableをNoneitertools.izip_longest似ていitertools.izip_longest )でitertools.izip_longestます。 Python 3では、反復は最短の反復可能性の後に停止します。

Python 2では:

Python 2.x 2.3
>>> map(None, [1, 2, 3], [1, 2], [1, 2, 3, 4, 5])
[(1, 1, 1), (2, 2, 2), (3, None, 3), (None, None, 4), (None, None, 5)]

Python 3では:

Python 3.x 3.0
>>> list(map(lambda x, y, z: (x, y, z), [1, 2, 3], [1, 2], [1, 2, 3, 4, 5]))
[(1, 1, 1), (2, 2, 2)]

# to obtain the same padding as in Python 2 use zip_longest from itertools
>>> import itertools
>>> list(itertools.zip_longest([1, 2, 3], [1, 2], [1, 2, 3, 4, 5]))
[(1, 1, 1), (2, 2, 2), (3, None, 3), (None, None, 4), (None, None, 5)]

注意map代わりに、リスト内包表記(Python 2/3互換)を使用することを検討してくださいmap(str, [1, 2, 3, 4, 5])置き換えmap(str, [1, 2, 3, 4, 5])

>>> [str(i) for i in [1, 2, 3, 4, 5]]
['1', '2', '3', '4', '5']

filter()、map()およびzip()はシーケンスの代わりにイテレータを返します

Python 2.x 2.7

Python 2のfiltermap関数とzip組み込み関数がシーケンスを返します。 mapzip常にリストを返しますが、 filterは戻り値の型は与えられたパラメータの型に依存します:

>>> s = filter(lambda x: x.isalpha(), 'a1b2c3')
>>> s
'abc'
>>> s = map(lambda x: x * x, [0, 1, 2])
>>> s
[0, 1, 4]
>>> s = zip([0, 1, 2], [3, 4, 5])
>>> s
[(0, 3), (1, 4), (2, 5)]
Python 3.x 3.0

Python 3 filter 、代わりにmapzipがイテレータを返します。

>>> it = filter(lambda x: x.isalpha(), 'a1b2c3')
>>> it
<filter object at 0x00000098A55C2518>
>>> ''.join(it)
'abc'
>>> it = map(lambda x: x * x, [0, 1, 2])
>>> it
<map object at 0x000000E0763C2D30>
>>> list(it)
[0, 1, 4]
>>> it = zip([0, 1, 2], [3, 4, 5])
>>> it
<zip object at 0x000000E0763C52C8>
>>> list(it)
[(0, 3), (1, 4), (2, 5)]

Python 2 itertools.izipはPython 3と同等ですzip izipはPython 3で削除されています。

絶対/相対輸入

Python 3では、 PEP 404はPython 2からのインポートの仕方を変更します。 暗黙の相対インポートはパッケージやfrom ... import * importsはモジュールレベルのコードでのみ許可されています。

Python 2でPython 3の動作を実現するには:

  • 絶対インポート機能はfrom __future__ import absolute_import有効にすることができますfrom __future__ import absolute_import
  • 明示的な相対輸入は、 暗黙の相対輸入の代わりに奨励される

明確にするために、Python 2では、モジュールは次のように同じディレクトリにある別のモジュールの内容をインポートできます:

import foo

fooの場所は、import文だけではあいまいであることに注意してください。このような暗黙の相対インポートは、 明示的な相対インポートを優先して行います。次のようになります。

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
from ...package import bar
from ...sys import path

ドット.ディレクトリツリー内のモジュール位置を明示的に宣言できます。


相対輸入の詳細

shapesと呼ばれるユーザー定義のパッケージについて考えてみましょう。ディレクトリ構造は次のとおりです。

shapes
├── __init__.py
|
├── circle.py
|
├── square.py
|
└── triangle.py

circle.pysquare.py 、およびtriangle.pyすべてモジュールとしてutil.pyをインポートします。同じレベルのモジュールをどのように参照するのでしょうか?

 from . import util # use util.PI, util.sq(x), etc

または

 from .util import * #use PI, sq(x), etc to call functions

.同じレベルの相対的なインポートに使用されます。

次に、 shapesモジュールの別のレイアウトを考えてみましょう。

shapes
├── __init__.py
|
├── circle
│   ├── __init__.py
│   └── circle.py
|
├── square
│   ├── __init__.py
│   └── square.py
|
├── triangle
│   ├── __init__.py
│   ├── triangle.py
|
└── util.py

さて、これらの3つのクラスはutil.pyをどのように参照しますか?

 from .. import util # use util.PI, util.sq(x), etc

または

 from ..util import * # use PI, sq(x), etc to call functions

..は、親レベルの相対インポートに使用され.. 。もっと追加してください.親と子の間のレベルの数を持つ。

ファイルI / O

fileはもはや3.xの組み込みの名前ではありません(まだopenいます)。

ファイルI / Oの内部の詳細は、標準ライブラリioモジュールに移されました。これはStringIO新しいホームです。

import io
assert io.open is open # the builtin is an alias
buffer = io.StringIO()
buffer.write('hello, ') # returns number of characters written
buffer.write('world!\n')
buffer.getvalue() # 'hello, world!\n'

ファイルモード(テキスト対バイナリ)は、ファイルを読み込むことによって生成されるデータのタイプ(および書き込みに必要なタイプ)を決定するようになりました。

with open('data.txt') as f:
    first_line = next(f)
    assert type(first_line) is str
with open('data.bin', 'rb') as f:
    first_kb = f.read(1024)
    assert type(first_kb) is bytes

テキストファイルのエンコーディングは、デフォルトでlocale.getpreferredencoding(False)によって返されるものになります。エンコードを明示的に指定するには、 encodingキーワードパラメータを使用します。

with open('old_japanese_poetry.txt', 'shift_jis') as text:
    haiku = text.read()

round()関数のタイブレークと戻り値の型

ラウンド()タイブレーク

Python 2では、2つの整数に等しく近い数にround()を使用すると、0から最も遠いものが返されます。例:

Python 2.x 2.7
round(1.5)  # Out: 2.0
round(0.5)  # Out: 1.0
round(-0.5)  # Out: -1.0
round(-1.5)  # Out: -2.0

しかし、Python 3では、 round()は偶数の整数を返します(別名銀行家の丸め )。例えば:

Python 3.x 3.0
round(1.5)  # Out: 2
round(0.5)  # Out: 0
round(-0.5)  # Out: 0
round(-1.5)  # Out: -2

ラウンド()関数は、以下の半分にも丸めに戦略その最も近い偶数の整数になりますが、ラウンド途中の番号(例えば、 round(2.5)今2なく、3.0を返します)。

Wikipediaの参考文献によると 、これは不偏丸め収束丸め統計学者の丸めオランダの丸めガウス丸め 、または奇数 - 偶数丸めとも呼ばれます

半分から偶数への丸めはIEEE 754標準の一部であり、Microsoftの.NETのデフォルトの丸めモードでもあります。

この丸め戦略は、丸め誤差の合計を減らす傾向があります。丸められた数値の量は平均して切り捨てられた数値の量と同じなので、丸め誤差はキャンセルされます。代わりに、他の丸め方法は、平均誤差に上方または下方バイアスを有する傾向がある。


round()戻り値の型

round()関数は、Python 2.7でfloat型を返します

Python 2.x 2.7
round(4.8)
# 5.0

Python 3.0から、2番目の引数(桁数)を省略すると、 int返します。

Python 3.x 3.0
round(4.8)
# 5

真、偽、なし

Python 2ではTrueFalseNoneは組み込み定数です。つまり、それらを再割り当てすることができます。

Python 2.x 2.0
True, False = False, True
True   # False
False  # True

Python 2.4以降、これをNone行うことはできません。

Python 2.x 2.4
None = None  # SyntaxError: cannot assign to None

Python 3では、 TrueFalseNoneはキーワードになりました。

Python 3.x 3.0
True, False = False, True  # SyntaxError: can't assign to keyword

None = None  # SyntaxError: can't assign to keyword

ファイルオブジェクトへの書き込み時の戻り値

Python 2では、ファイルハンドルに直接書き込むとNoneが返されます。

Python 2.x 2.3
hi = sys.stdout.write('hello world\n')
# Out: hello world
type(hi)
# Out: <type 'NoneType'>

Python 3では、ハンドルに書き込むと、テキストを書き込むときに書き込まれる文字数と、バイトを書き込むときに書き込まれるバイト数が返されます。

Python 3.x 3.0
import sys

char_count = sys.stdout.write('hello world 🐍\n')
# Out: hello world 🐍
char_count
# Out: 14

byte_count = sys.stdout.buffer.write(b'hello world \xf0\x9f\x90\x8d\n')
# Out: hello world 🐍
byte_count
# Out: 17

長い対int

Python 2では、C ssize_tより大きい任意の整数が、リテラルにL接尾辞で示されるlongデータ型に変換されます。たとえば、Pythonの32ビットビルドでは、次のようになります。

Python 2.x 2.7
>>> 2**31
2147483648L
>>> type(2**31)
<type 'long'>
>>> 2**30
1073741824
>>> type(2**30)
<type 'int'>
>>> 2**31 - 1  # 2**31 is long and long - int is long
2147483647L

しかし、Python 3では、 longデータ型が削除されました。整数がどれほど大きくてもintます。

Python 3.x 3.0
2**1024
# Output: 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
print(-(2**1024))
# Output: -179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
type(2**1024)
# Output: <class 'int'>

クラスブール値

Python 2.x 2.7

Python 2では、クラスのブール値を自分で定義する場合は、クラスに__nonzero__メソッドを実装する必要があります。値はデフォルトでTrueです。

class MyClass:
    def __nonzero__(self):
        return False

my_instance = MyClass()
print bool(MyClass)       # True
print bool(my_instance)   # False
Python 3.x 3.0

Python 3では、 __bool__代わりに__nonzero__が使用されています

class MyClass:
    def __bool__(self):
        return False

my_instance = MyClass()
print(bool(MyClass))       # True
print(bool(my_instance))   # False


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow