2016 年を覚えていますか?世界中がポケモン GO とリオオリンピックで忙しい中、私は目を丸くして初めての「Hello, World!」を書いていた大学生でした。 Pythonで。当時、私は辞書の順序の保存が何を意味するのか、ましてや Python コミュニティが次期 3.6 リリースに辞書の順序を含めることについて騒いでいた理由をまったく知りませんでした。経験豊富な開発者として振り返ってみると、Python と私がここまで進歩できたことは驚くべきことです。
3.6 の f-strings から 3.10 の革新的なパターン マッチング、そして現在の 3.13 のフリー スレッド機能に至るまで、Python は一貫して、よりクリーンで表現力豊かなコードで達成できる限界を押し広げてきました。それは、お気に入りのスーパーヒーローが映画ごとに新しい力を獲得するのを見るようなものです。ただし、ウェブを撃ったり、ハンマーを振り回したりする代わりに、コードの複雑さと冗長さという、本当の悪役と戦うためのより良いツールを手に入れることができます。
この記事では、タイムマシンを起動して、3.6 から 3.13 までの Python の各バージョンに導入された最も重要な機能について説明します。各リリースの主な機能を見て、それらの機能が Python コードの記述方法をどのように変えたかを探っていきます。思い出を振り返りたいベテランの Pythonista も、言語の進化に興味のある初心者も、シートベルトを締めて、Python の歴史を巡るエキサイティングな旅を楽しみましょう!
この旅が終わる頃には、あなたは古いコードを見てこう思っているかもしれません 「ああ、これらの機能なしでどうやって生きていたのでしょう?」 それでは、私たちのお気に入りがどのように機能するのかを見てみましょう。ヘビは何年にもわたって脱皮し、変化するたびにより強く、より強力になってきました。
Python 開発者を集めて安堵のため息をついた機能が 1 つあるとすれば、それは f-strings です。 .format() と % フォーマットの時代を覚えていますか? F 文字列は、冗長な文字列フォーマットの悪夢から私たちを救ってくれました。
# The old ways name, language, year = "Alice", "Python", 2016 print("{} started learning {} in {}".format(name, language, year)) # .format() print("%s started learning %s in %d" % (name, language, year)) # % formatting # The f-string way print(f"{name} started learning {language} in {year}") # But wait, there's more! F-strings can handle expressions items = ["code", "coffee", "bugs"] print(f"Developer life: {', '.join(items[:-1])} and {items[-1]}") print(f"Hours coding today: {8 * 2}") # Math? No problem! # They even work with method calls message = " python rocks " print(f"Confession: {message.strip().title()}")
大量の数値を扱う私たちにとって、この機能は状況を大きく変えるものでした。画面上でゼロを数える必要はもうありません!
# The old ways name, language, year = "Alice", "Python", 2016 print("{} started learning {} in {}".format(name, language, year)) # .format() print("%s started learning %s in %d" % (name, language, year)) # % formatting # The f-string way print(f"{name} started learning {language} in {year}") # But wait, there's more! F-strings can handle expressions items = ["code", "coffee", "bugs"] print(f"Developer life: {', '.join(items[:-1])} and {items[-1]}") print(f"Hours coding today: {8 * 2}") # Math? No problem! # They even work with method calls message = " python rocks " print(f"Confession: {message.strip().title()}")
型ヒントは以前から存在していましたが、Python 3.6 では変数アノテーションを使用してより柔軟になりました。これにより、よりクリーンな型ヒンティングが可能になり、より優れた静的分析への道が開かれました。
# Before: Is this a billion or a million? ? old_budget = 1000000000 # After: Crystal clear! ? new_budget = 1_000_000_000 # Works with different number types hex_address = 0xFF_FF_FF_FF # Much easier to read! binary_flag = 0b_1111_0000 # Grouping bits
おまけのヒント: これらの注釈は実行時の動作には影響しません。開発者とツールに対するヒントです。しかし、これらを使用すると、IDE のオートコンプリートが魔法のように機能します。 ✨
大量の __init__ パラメーターを含むクラスを作成し、それぞれに苦労して割り当てたのを覚えていますか?データクラスは、__init__、__repr__、__eq__ などの定型コードを自動生成することにより、クラスの作成を簡素化しました。
# Before Python 3.6 (still works, but less flexible) def get_user_data(user_id: int) -> dict: pass # Python 3.6 style from typing import Dict, List, Optional # Class attributes with type hints class UserDataAnalyzer: premium_users: List[int] = [] cache: Dict[int, str] = {} last_analyzed: Optional[str] = None def analyze_user(self, user_id: int) -> None: # Some analysis logic here self.last_analyzed = "2024-10-07"
この機能は退屈に思えますが、大きな問題を解決しました。前方参照が有効になり、遅延評価によるパフォーマンスが向上しました。
from dataclasses import dataclass from datetime import datetime # Before dataclasses ? class OldBooking: def __init__(self, id, destination, traveler, date, price): self.id = id self.destination = destination self.traveler = traveler self.date = date self.price = price def __repr__(self): return f"Booking({self.id}, {self.destination}, {self.traveler})" def __eq__(self, other): return isinstance(other, OldBooking) and self.id == other.id # After dataclasses ? @dataclass class Booking: id: int destination: str traveler: str date: datetime price: float def total_with_tax(self, tax_rate: float = 0.1) -> float: return self.price * (1 + tax_rate) # Using our dataclass trip = Booking( id=42, destination="Python Island", traveler="Pythonista", date=datetime.now(), price=199.99 ) print(f"Trip cost with tax: ${trip.total_with_tax():.2f}")
import pdb と入力する時代は終わりました。 pdb.set_trace()。これで、ブレークポイント() を削除して、通常の生活を続けることができます!
from __future__ import annotations from typing import List class ChessGame: def __init__(self): self.players: List[Player] = [] # This now works! self.board: Board = Board() # This too! def add_player(self, player: Player) -> None: self.players.append(player) def get_winner(self) -> Player | None: # Python 3.10 union type just for fun! # Game logic here return None class Player: def __init__(self, name: str, rating: int): self.name = name self.rating = rating class Board: def __init__(self): self.moves: List[tuple[Player, str]] = []
デバッグのヒント: ブレークポイントの動作を制御するには、PYTHONBREAKPOINT 環境変数を設定します。
def calculate_universe_answer(): numbers = list(range(43)) breakpoint() # Your IDE probably supports this better than pdb! return sum(numbers) - 903 def main(): print("Calculating the answer to life, universe, and everything...") result = calculate_universe_answer() print(f"The answer is: {result}") # When you run this, you'll drop into a debugger at the breakpoint # Try these in the debugger: # - 'numbers' to see the list # - 'len(numbers)' to check its length # - 'n' to go to next line # - 'c' to continue execution
Python 3.7 は 3.6 ほど派手ではなかったかもしれませんが、重大な生活の質の向上をもたらしました。データクラスだけでも、おそらく世界中で何百万ものキーストロークが節約されたでしょう。デバッグを容易にするものはすべて、金メッキの Python に価値があります。
最も物議を醸しているものの、Python への強力な追加機能。これにより、より大きな式の一部として変数に値を割り当てることができます。
セイウチ オペレーターを使用すると、次の 2 つのことを同時に行うことができます:
# Disable all breakpoints export PYTHONBREAKPOINT=0 # Use a different debugger (like IPython's) export PYTHONBREAKPOINT=IPython.embed
「これらの引数はここにあります。質問はありません!」と言いたい場合。キーワードではなく位置によって渡す必要がある引数を指定できます。この機能により API 設計の柔軟性が向上し、関数シグネチャの重大な変更を防ぐことができます。
# Consider this code example: while True: user_input = input("Enter something (or 'quit' to exit): ") if user_input == 'quit': break print(f"You entered: {user_input}") # We can simplify above code using walrus operator like this: while (user_input := input("Enter something (or 'quit' to exit): ")) != 'quit': print(f"You entered: {user_input}")
f-strings 内に = のサポートが追加され、デバッグが容易になりました。
def create_character(name, /, health=100, *, special_move): return f"{name}: {health}HP, Special: {special_move}" # These work player1 = create_character("Pythonista", special_move="Code Sprint") player2 = create_character("Bug Slayer", health=120, special_move="Debug Strike") # This fails - name must be positional # player3 = create_character(name="Syntax Error", special_move="Crash Game")
セイウチ オペレーターにより、より簡潔なコードを作成できるようになり (ただし、大きな力には大きな責任が伴います!)、位置のみのパラメーターにより、関数インターフェイスをより詳細に制御できるようになり、f-string デバッグにより、印刷デバッグが実際に快適になりました。
ついに、Python は辞書を結合するきれいな方法を提供してくれました。 dict1.update(dict2) と書くか、{**dict1, **dict2} を使用しなければならなかった時代を覚えていますか?あの日々はもう終わりです。
# The old ways name, language, year = "Alice", "Python", 2016 print("{} started learning {} in {}".format(name, language, year)) # .format() print("%s started learning %s in %d" % (name, language, year)) # % formatting # The f-string way print(f"{name} started learning {language} in {year}") # But wait, there's more! F-strings can handle expressions items = ["code", "coffee", "bugs"] print(f"Developer life: {', '.join(items[:-1])} and {items[-1]}") print(f"Hours coding today: {8 * 2}") # Math? No problem! # They even work with method calls message = " python rocks " print(f"Confession: {message.strip().title()}")
この追加により、typeing.List、typing.Dict などの必要がなくなり、型の注釈が簡素化されました。
# Before: Is this a billion or a million? ? old_budget = 1000000000 # After: Crystal clear! ? new_budget = 1_000_000_000 # Works with different number types hex_address = 0xFF_FF_FF_FF # Much easier to read! binary_flag = 0b_1111_0000 # Grouping bits
これらは単純に見えるかもしれませんが、テキスト処理には非常に強力です。面倒な文字列のスライスや、ハードコードされた長さでの replace() 呼び出しはもう必要ありません!
# Before Python 3.6 (still works, but less flexible) def get_user_data(user_id: int) -> dict: pass # Python 3.6 style from typing import Dict, List, Optional # Class attributes with type hints class UserDataAnalyzer: premium_users: List[int] = [] cache: Dict[int, str] = {} last_analyzed: Optional[str] = None def analyze_user(self, user_id: int) -> None: # Some analysis logic here self.last_analyzed = "2024-10-07"
Python 3.10 (2021 年 10 月リリース) では、非常に優れたパターン マッチング機能が追加されました。
Switch ケースはここ 10 年でそうでした。パターン マッチングは、データ構造に対するスイス アーミー ナイフのように登場しました。単に値を一致させるだけではありません。コードソムリエの優雅さでデータを分解することです。
from dataclasses import dataclass from datetime import datetime # Before dataclasses ? class OldBooking: def __init__(self, id, destination, traveler, date, price): self.id = id self.destination = destination self.traveler = traveler self.date = date self.price = price def __repr__(self): return f"Booking({self.id}, {self.destination}, {self.traveler})" def __eq__(self, other): return isinstance(other, OldBooking) and self.id == other.id # After dataclasses ? @dataclass class Booking: id: int destination: str traveler: str date: datetime price: float def total_with_tax(self, tax_rate: float = 0.1) -> float: return self.price * (1 + tax_rate) # Using our dataclass trip = Booking( id=42, destination="Python Island", traveler="Pythonista", date=datetime.now(), price=199.99 ) print(f"Trip cost with tax: ${trip.total_with_tax():.2f}")
Python 3.10 では、かっこを使用して複数のコンテキスト マネージャーを処理するクリーンな方法が導入されました。
from __future__ import annotations from typing import List class ChessGame: def __init__(self): self.players: List[Player] = [] # This now works! self.board: Board = Board() # This too! def add_player(self, player: Player) -> None: self.players.append(player) def get_winner(self) -> Player | None: # Python 3.10 union type just for fun! # Game logic here return None class Player: def __init__(self, name: str, rating: int): self.name = name self.rating = rating class Board: def __init__(self): self.moves: List[tuple[Player, str]] = []
Python は、「AttributeError」では十分に役に立たないと判断し、「もしかして...」という提案を選択しました。これは、間違いを指摘するだけでなく、実際に手助けをしてくれるコードレビュー担当者が組み込まれているようなものです。
def calculate_universe_answer(): numbers = list(range(43)) breakpoint() # Your IDE probably supports this better than pdb! return sum(numbers) - 903 def main(): print("Calculating the answer to life, universe, and everything...") result = calculate_universe_answer() print(f"The answer is: {result}") # When you run this, you'll drop into a debugger at the breakpoint # Try these in the debugger: # - 'numbers' to see the list # - 'len(numbers)' to check its length # - 'n' to go to next line # - 'c' to continue execution
面白い事実: パターン マッチング構文は Rust やその他の関数型プログラミング言語からインスピレーションを得たものですが、Python によってより Python らしくなりました。 Scala や Elixir などの言語から来ている方でも、安心してご利用いただけます!
Python 3.11 は、私たち全員が切望していたもの、つまり速度の大幅な向上をもたらしました。このリリースはただ速いだけではありませんでした。 「Python 3.10 よりも最大 60%」高速で、平均では 25% 高速でした。しかし、それがもたらしたものはそれだけではありません。このバージョンを特別なものにした最もエキサイティングな機能について説明します。
これはコードで「確認できる」機能ではありませんが、間違いなく感じられる機能です。 Python 3.11 では、コードの実行を大幅に高速化する特殊な適応型インタープリターが導入されました。これを示す簡単な例を次に示します。
# Disable all breakpoints export PYTHONBREAKPOINT=0 # Use a different debugger (like IPython's) export PYTHONBREAKPOINT=IPython.embed
速度の向上は、CPU を大量に使用するタスク、エラー処理、および深くネストされた関数呼び出しで特に顕著です。まるで Python がジムに行って、これまで以上に元気になって戻ってきたようなものです。 ?
この機能は、複数のエラーが同時に発生する可能性がある同時操作を処理する場合の救世主です。 1 つの例外をキャッチする代わりに、複数の例外をグループとして処理できるようになりました!
# The old ways name, language, year = "Alice", "Python", 2016 print("{} started learning {} in {}".format(name, language, year)) # .format() print("%s started learning %s in %d" % (name, language, year)) # % formatting # The f-string way print(f"{name} started learning {language} in {year}") # But wait, there's more! F-strings can handle expressions items = ["code", "coffee", "bugs"] print(f"Developer life: {', '.join(items[:-1])} and {items[-1]}") print(f"Hours coding today: {8 * 2}") # Math? No problem! # They even work with method calls message = " python rocks " print(f"Confession: {message.strip().title()}")
Python 3.11 では、エラーをより正確に特定することで開発者の生産性が向上しました。まるでデバッグ アシスタントが組み込まれているようなものです!
# Before: Is this a billion or a million? ? old_budget = 1000000000 # After: Crystal clear! ? new_budget = 1_000_000_000 # Works with different number types hex_address = 0xFF_FF_FF_FF # Much easier to read! binary_flag = 0b_1111_0000 # Grouping bits
これらのエラー メッセージは、複雑な数学演算やネストされたメソッド呼び出しを処理する場合に特に役立ちます。もう手動で括弧を数える必要はありません!
Python 3.11 は単なる増分アップデートではなく、パフォーマンスと開発者のエクスペリエンスの点で大きな進歩を遂げました。速度の向上だけでも魅力的なアップグレードですが、新しい例外処理機能と強化されたエラー メッセージを追加すると、まさに「スピードスター」の称号にふさわしいリリースが手に入ります!
Python 3.12 では、f-string がさらに良くなりました。以前のバージョンにはいくつかの制限がありました。f 文字列内にバックスラッシュやコメントは使用できず、複雑な式には回避策が必要になる場合がありました。
# Before Python 3.6 (still works, but less flexible) def get_user_data(user_id: int) -> dict: pass # Python 3.6 style from typing import Dict, List, Optional # Class attributes with type hints class UserDataAnalyzer: premium_users: List[int] = [] cache: Dict[int, str] = {} last_analyzed: Optional[str] = None def analyze_user(self, user_id: int) -> None: # Some analysis logic here self.last_analyzed = "2024-10-07"
TypeVar または Generic を明示的にインポートする必要がなくなり、機能を犠牲にすることなく定型文が削減され、コードの可読性が向上します。
from dataclasses import dataclass from datetime import datetime # Before dataclasses ? class OldBooking: def __init__(self, id, destination, traveler, date, price): self.id = id self.destination = destination self.traveler = traveler self.date = date self.price = price def __repr__(self): return f"Booking({self.id}, {self.destination}, {self.traveler})" def __eq__(self, other): return isinstance(other, OldBooking) and self.id == other.id # After dataclasses ? @dataclass class Booking: id: int destination: str traveler: str date: datetime price: float def total_with_tax(self, tax_rate: float = 0.1) -> float: return self.price * (1 + tax_rate) # Using our dataclass trip = Booking( id=42, destination="Python Island", traveler="Pythonista", date=datetime.now(), price=199.99 ) print(f"Trip cost with tax: ${trip.total_with_tax():.2f}")
Python の長年の問題点の 1 つは、一度に 1 つのスレッドのみが Python バイトコードを実行できるようにするメカニズムであるグローバル インタープリター ロック (GIL) です。これにより、マルチスレッド プログラム、特に CPU に依存するタスクでパフォーマンスのボトルネックが発生しました。ただし、Python 3.12 では、インタープリターごとの GIL という大幅な改善が導入されています。
簡単に言えば、GIL は Python が実際に複数のスレッドを同時に実行することを防ぎます。スレッドは I/O バウンドの操作 (ファイルの読み取りやネットワーク リクエストの実行など) によく使用されますが、GIL は CPU を大量に使用するワークロードに対するマルチスレッドの利点を制限します。これは、マルチコア プロセッサを活用する必要がある Python 開発者にとって、長年の課題でした。
Python 3.12 では、インタープリターに独自の GIL が追加され、単一のグローバル ロックに制約されることなく、同じプロセス内の複数のインタープリターを並行して実行できるようになりました。これは、マルチコア処理に特に役立ちます。 ただし、Python 3.12 は、C-API を介したインタープリターごとの GIL のみをサポートします。 Python-API の完全なサポートは Python 3.13 で追加される予定です。
この機能の詳細:
Python 3.12 は、3.11 のような即時のパフォーマンスへの影響はないかもしれませんが、型システムのエルゴノミクスと f-string 機能の改善により、保守可能でタイプセーフなコードを作成するための重要なリリースとなっています。これらの機能は、コードの明確さと型の安全性が重要である大規模なプロジェクトで特に価値があります。
Python 3.13 は Read-Eval-Print-Loop (REPL) を強化し、よりスマートでユーザーフレンドリーになりました。 REPL は、複数行のコードをより効果的に実行し、より適切な構文の提案を表示し、オートコンプリートのエクスペリエンスを向上させることができるようになりました。
新しい REPL には次の新機能があります:
長年にわたり、Python 開発者は、複数のネイティブ スレッドが Python バイトコードを同時に実行することを防ぐメカニズムである、グローバル インタープリター ロック (GIL) をめぐる微妙な動きに巻き込まれてきました。 GIL には利点もありますが、マルチスレッド アプリケーションにとってはボトルネックでもあります。
Python 3.13 のフリー スレッド モードは、GIL を無効にすることでこれらのチェーンを断ち切ることを目的としています。これにより、マルチスレッド Python プログラムでの真の並列処理が可能になります。基本的に、スレッドを同時に実行できるようになり、マルチコア プロセッサを最大限に活用できるようになります。以前のバージョンでは、GIL はこれらのスレッドを一度に 1 つずつ強制的に実行し、実行を効果的にシリアル化していました。
macOS または Windows 用のインストーラーをダウンロードできます。これらにはフリースレッド オプションがあります。または、pyenv を使用してソースからビルドしてインストールすることもできます (推奨): pyenv install 3.13.0t
注: フリースレッド モードは Python の進化における大きな進歩ですが、実験的なステータスであることを念頭に置くことが重要です (いくつかのバグが予想されます)。さらに、フリースレッド ビルドでは、無効化された特殊な適応型インタープリター (PEP 659) により、シングル スレッドのパフォーマンスが 40% 低下します。
実験的なジャストインタイム (JIT) コンパイラーは、Python の進化におけるもう 1 つの重要なマイルストーンを示します。 JIT コンパイラーは、実行時に Python バイトコードをマシンコードに動的に変換することによって機能します。これは、「コピーアンドパッチ」と呼ばれる手法を使用して行われます。これは、頻繁に実行されるコード パスがオンザフライでコンパイルされることを意味し、理論的にはコードの重要なセクションのパフォーマンスが大幅に向上する可能性があります。
さて、まだ興奮しすぎないでください。現在の形式では、JIT コンパイラーはコードを高速化することを目的としたものではなく、通常の Python パフォーマンスを維持することだけを目的としています。しかし、プロセスに追加のステップを追加しながらこれを実行しているのは、非常に印象的です。 Python チームは、この小さなエンジンについて大きな計画を立てており、将来のバージョンで改良して、メモリを消費せずに実際の速度を向上させたいと考えています。現時点では、コンセプトを証明し、将来の最適化のための基礎を築くことに重点を置いています。旅の締めくくりですか?
それでは、パイソンニスタの皆さん、これまでの栄光に満足しないでください。今日の Python は、昨日学んだ Python ではありません。明日の Python は、また私たちを驚かせるかもしれません。探索を続け、学習を続け、この 2 つの単純な単語で可能なことの限界を押し広げ続けてください: import this
この記事はもともと私の個人ブログに公開されたものです。
以上がPythonic Time Capsule: 各バージョンの知っておくべき機能の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。