Pythonは現在、データサイエンスやAI開発、Webアプリケーション制作など、幅広い分野で最も人気のあるプログラミング言語の一つです。
しかし、Pythonの歴史を辿ると、Python 2系とPython 3系の間で発生した大きな仕様変更という重要な転換点があります。
2020年1月1日にPython 2のサポートが完全に終了した現在、新規開発でPython 2が選ばれることはありませんが、既存システムのメンテナンスやレガシーコードの移行において、両者の違いを正確に理解しておくことはエンジニアにとって必須の知識と言えます。
Python 2とPython 3の歴史的背景と移行の理由
Python 3は、2008年12月に「言語としての矛盾を解消し、よりクリーンなコードを書けるようにする」という目的でリリースされました。
しかし、Python 3はPython 2との後方互換性をあえて持たせないという大きな決断を下したため、コミュニティや企業が完全に移行を完了するまでには10年以上の歳月を要することとなりました。
Python 3が開発された目的
Python 2は非常に優れた言語でしたが、開発が進むにつれて「同じことを行うのに複数の方法がある」といった冗長性や、文字コードの扱いの複雑さ、整数同士の計算結果の不自然さなど、設計上の細かな課題が蓄積していました。
Python 3では、これらの設計上の欠陥を抜本的に修正し、より一貫性のある直感的な言語へと進化を遂げました。
Python 2のサポート終了 (EOL)
Python 2.7は、2020年1月1日をもってセキュリティアップデートを含むすべてのサポートが終了しました。
これにより、Python 2を使い続けることは重大なセキュリティリスクを伴うことになりました。
現在の主要なライブラリ (NumPy, Pandas, TensorFlowなど) もすべてPython 3のみをサポートしており、Python 3への完全移行は不可避な状況です。
基本的な構文の違い
Python 2とPython 3の最も顕著な違いは、日常的に使用する基本的な関数や演算の挙動にあります。
print文からprint関数への変更
最も有名な違いは print の扱いです。
Python 2では文 (Statement) でしたが、Python 3では関数 (Function) に変更されました。
Python 2の例
# Python 2では括弧が不要な文として扱われる
print "Hello, Python 2"
# 複数の値を出力する場合、タプルとして解釈される可能性がある
print "Value:", 10
Python 3の例
# Python 3では関数なので必ず括弧 () が必要
print("Hello, Python 3")
# キーワード引数 (endやsep) が使用可能になり、柔軟性が向上
print("Value:", 10, sep=" = ")
Hello, Python 3
Value: = 10
整数の除算 (割り算) の挙動
数値計算において、最も注意が必要なのが割り算の挙動です。
Python 2では、整数同士の割り算の結果は「切り捨てられた整数」になりますが、Python 3では「浮動小数点数 (float)」を返します。
| 演算式 | Python 2の結果 | Python 3の結果 |
|---|---|---|
3 / 2 | 1 | 1.5 |
4 / 2 | 2 | 2.0 |
3 // 2 | 1 | 1 (切り捨て除算) |
Python 2で1.5を得るためには、3 / 2.0 のように明示的に浮動小数点数を含める必要がありました。
Python 3ではこの直感に反する挙動が修正されています。
文字列とUnicodeの扱い
Python 2と3の最大の違いであり、移行を最も困難にしたのが文字コードの取り扱いです。
Python 2の文字列
Python 2のデフォルトの文字列型は、実際には「バイト列」です。
日本語などのマルチバイト文字を扱うには、接頭辞 u を付けて u"こんにちは" のようにUnicode文字列として明示する必要がありました。
Python 3の文字列
Python 3では、デフォルトの文字列型 (str) が標準でUnicode文字列になりました。
一方、画像データやネットワーク通信で扱うバイナリデータは bytes 型として厳格に区別されるようになりました。
これにより、「文字列とバイト列を暗黙的に結合する」といったバグの原因が排除されました。
反復処理と組み込み関数の変更
効率的なデータ処理を行うための組み込み関数や反復処理の仕組みも、Python 3で大きく改善されました。
range関数とxrange関数の統合
Python 2には、リストを生成する range() と、イテレータを生成する xrange() の2種類が存在しました。
range(1000000): Python 2では、100万個の要素を持つリストをメモリ上に作成するため、メモリを大量に消費します。xrange(1000000): 必要な時に値を生成するため、メモリ効率が良いです。
Python 3では、従来の range() が廃止され、Python 2のxrangeと同じ挙動をするものがrange()として採用されました。
これにより、大量のデータを扱う際も意識せずにメモリ効率の良いコードが書けるようになっています。
リストを返す関数がビューやイテレータに変更
Python 3では、メモリ消費を抑えるために、多くの関数がリストの代わりに「ビュー (View)」や「イテレータ (Iterator)」を返すようになりました。
dict.keys(),dict.values(),dict.items():Python 2ではリストを返していましたが、Python 3では動的なビューオブジェクトを返します。map(),filter(),zip():Python 2ではリストを返していましたが、Python 3ではイテレータを返します。
リストとして扱いたい場合は、list(map(...)) のように明示的にキャストする必要があります。
開発を支えるその他の重要な違い
例外処理の構文
例外をキャッチする際の構文も、より明確に変更されました。
Python 2
try:
# 処理
pass
except ValueError, e: # カンマ区切り
print e
Python 3
try:
# 処理
pass
except ValueError as e: # asキーワードを使用
print(e)
Python 2のカンマ形式では、複数の例外を指定する場合と混同しやすかったため、Python 3では as の使用が必須となりました。
入力関数の統合
ユーザー入力を受け取る関数も変更されています。
- Python 2:
raw_input()が文字列を返し、input()は入力をPythonコードとして評価 (eval) してしまいました。 - Python 3:
raw_input()が廃止され、input()が常に文字列を返す安全な設計になりました。
Python 2からPython 3への移行プロセス
既存のPython 2プロジェクトをPython 3へ移行(マイグレーション)する場合、手作業ですべて書き換えるのは現実的ではありません。
以下のツールやライブラリを活用するのが一般的です。
2to3 ツールの活用
Python標準ライブラリには、Python 2のコードを解析してPython 3のコードへ自動変換する 2to3 というユーティリティが含まれています。
# ファイルを変換して差分を表示
$ 2to3 my_script.py
# 実際にファイルを書き換える
$ 2to3 -w my_script.py
ただし、完全に自動で変換できないケース(特に文字コード関連)も多いため、変換後の動作確認(ユニットテスト)は必須です。
six ライブラリの利用
Python 2と3の両方の環境で動作する「共通コード」を書きたい場合は、six ライブラリが便利です。
six.PY2 や six.PY3 といったフラグを使って、環境に応じた処理の切り替えが可能です。
__future__ モジュールの利用
Python 2のコード内で Python 3の機能を先取りして使用することも可能です。
移行の初期段階でこれを導入することで、Python 3への適応をスムーズにします。
# Python 2環境でもPython 3の挙動を適用する
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals
Python 3で導入された魅力的な新機能
Python 2にはなく、Python 3だけで利用できる強力な機能は、開発効率を劇的に向上させます。
f-strings (フォーマット済み文字列リテラル)
Python 3.6から導入された f-strings は、変数や式を文字列内に埋め込む最も簡潔で高速な方法です。
name = "Python"
version = 3.12
# 変数を直接埋め込める
print(f"Welcome to {name} version {version}")
型ヒント (Type Hints)
Python 3.5以降、変数や関数の引数・戻り値に型情報を付与できるようになりました。
これにより、大規模開発における可読性とバグ発見の効率が飛躍的に高まりました。
def greeting(name: str) -> str:
return "Hello, " + name
非同期処理 (asyncio)
async や await キーワードを用いた非同期プログラミングが標準サポートされました。
大量のI/O待ちが発生するネットワークアプリケーションなどで威力を発揮します。
まとめ
Python 2とPython 3の違いは、単なるマイナーアップデートではなく、言語の整合性と将来性を確保するための大規模な再設計の結果です。
- print:文から関数へ。
- 数値計算:整数同士の割り算が浮動小数点数を返すように。
- 文字列:デフォルトがUnicodeになり、国際化対応が容易に。
- 効率性:イテレータの活用によりメモリ消費が最適化。
- 新機能:f-stringsや型ヒント、非同期処理などモダンな開発機能が充実。
現在、Python 2はすでにその役割を終えており、セキュリティやライブラリの観点からもPython 3への移行は必須となっています。
これからPythonを学ぶ方、あるいは古いコードを扱っている方は、これらの違いをしっかりと把握し、最新のPython 3が持つ強力な機能を最大限に活用していくことが重要です。






