Python学習チャンネル by PyQ

Pythonのオンライン学習プラットフォームPyQのオフィシャルブログです

2023年10月に正式版が公開されるPython 3.12について紹介します

次のPythonのバージョンである Python 3.12は、2023年10月に正式リリース予定です。

本記事では、Python 3.12の更新内容を紹介します。

Pythonのリリースについて

Python 3.12の正式版までのリリーススケジュールはPEP 693で公開され、概ねそのスケジュールに沿って開発が進められています。

2023年7月19日現在の時点では3.12.0 beta 4が公開されており、beta 4以降のスケジュールは以下のとおりです。

  • 3.12.0 candidate 1: Monday, 2023-07-31
  • 3.12.0 candidate 2: Monday, 2023-09-04
  • 3.12.0 final: Monday, 2023-10-02

candidateというのは正式版になる予定のバージョンのことです。 candidate後はバグフィックスのみで機能の変更は原則行われないので、candidateでも新機能を試すのには十分です。

それでは、今回は Python 3公式ドキュメント - What's New In Python 3.12 より、Python 3.12の更新内容を4つ紹介します。

f-strings のPython構文への対応

この機能について、ドキュメントには「Syntactic formalization of f-strings」とあり、直訳すると「f-stringsの構文形式化」です。
「構文形式化」と言われてもよく分かりませんね。
実質的には、この後説明するように「f-strings 中に書ける式がPythonの構文に対応した」という変更です。

Pythonのf-stringsは、「 f"" で囲んだ文字列中の {} 内にPythonの式が書ける」というものですが、Python 3.11までは{} 内に書ける式にいくつか制限がありました。
Python 3.12 ではそれらの制限がなくなり、式がより書きやすくなります。

それでは、どのように変わるのか見ていきましょう。

クォーテーション記号を再利用できる

Python 3.11 ではf"" のように、f-stringsを記述するのに " で囲んでしまうと、 {} の中で " は使えませんでした。

Python 3.12 では、 以下のようにf-strings の囲みに使ったクォーテーション記号を、{}内でも使えるようになります(Python 3.11 ではSyntaxErrorになります)。

>>> songs = ['Take me back to Eden', 'Alkaline', 'Ascensionism']
>>> f"This is the playlist: {", ".join(songs)}"
'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'

これにより、以下のようにf-stringsを入れ子にすることも可能となります。

>>> f"{f"{f"{f"{f"{f"{1+1}"}"}"}"}"}"
'2'

複数行の式およびコメントが書ける

Python 3.11 では、f-strings の式が複数行になる場合、たとえ結果の文字列が1行だったとしても三連クォーテーションで囲む必要がありました。

そのため、Python 3.11では以下のように書かねばなりません。

>>> f"""This is the playlist: {', '.join([
...     'Take me back to Eden',
...     'Alkaline',
...     'Ascensionism'
... ])}"""
'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'

また、式が長いとコメントが書きたくなることもありますが、Python 3.11では式内に # でコメントは書けませんでした。

Python 3.12では、f-strings の式が複数行になる場合でも三連クォーテーションを使う必要がなくなります。また、式内に # でコメントも記述でき、以下のように書けます。

>>> f"This is the playlist: {', '.join([
...     'Take me back to Eden',  # My, my, those eyes like fire
...     'Alkaline',              # Not acid nor alkaline
...     'Ascensionism'           # Take to the broken skies at last
... ])}"
'This is the playlist: Take me back to Eden, Alkaline, Ascensionism'

バックスラッシュを書ける

Python 3.11では、f-stringsの式にバックスラッシュ(\)が書けず、改行文字( "\n" )などが使えませんでした。

Python 3.12 では、以下のようにf-stringsの式にバックスラッシュ(\)を書けるようになります(Python 3.11 ではSyntaxErrorになります)。

>>> print(f"This is the playlist: {'\n'.join(songs)}")
This is the playlist: Take me back to Eden
Alkaline
Ascensionism

TypedDictを使った可変長キーワード引数の型ヒント

この機能について、ドキュメントには「Using TypedDict for more precise **kwargs typing」とあります。こちらは型ヒントの書き方についての新機能です。

Pythonの関数やメソッドには、引数名: 型名 で引数に型ヒントを記述できます。
また、引数に**kwargs と書くことで、引数をキーワード可変長引数にできます。

では以下のように書くと、kwargsの型はどうなるでしょうか。

def foo(**kwargs: str) -> None: ...

この場合、kwargs の型は dict[str, str]と見なされます。

これを踏まえて、TypedDictを使って以下のようなMovie型を定義し、Movieで定義された項目(nameyear)を関数の引数に指定したい場合を考えてみましょう。

from typing import TypedDict

class Movie(TypedDict):
    name: str
    year: int

たとえば以下のように書いてしまうと、kwargs の型は dict[str, Movie]と見なされてしまいます。

def foo(**kwargs: Movie) -> None: ...

そこで、Python 3.12では **kwargs: Unpack[Movie] と書けるようになりました。

from typing import Unpack

def foo(**kwargs: Unpack[Movie]): ...

このようにすると、型チェッカーが以下のように判定します。

# 正しい
typed_movie: Movie = {"name": "The Meaning of Life", "year": 1983}
foo(**typed_movie)                          # OK!
foo(name="The Meaning of Life", year=1983)  # OK!

# 間違い
movie: dict[str, object] = {"name": "Life of Brian", "year": 1979}
foo(**movie)  # NG!

これにより、関数やメソッドが多くの引数をもつ場合に、その引数をよりシンプルに記述できそうです。

typing.override() デコレーターの追加

この機能について、ドキュメントでは「Override Decorator for Static Typing」とあります。こちらはクラスの継承に関する新機能です。

Python 3.12では、typing モジュールに typing.override() デコレータが追加されます。

これを使うと、クラスのメソッドがスーパークラスのメソッドをオーバーライドするものであることを、型チェッカーに指定できます。

サンプルは以下のとおりです。

from typing import override

class Base:
  def get_color(self) -> str:
    return "blue"

class GoodChild(Base):
  @override  # OK: Base.get_color をオーバーライド
  def get_color(self) -> str:
    return "yellow"

class BadChild(Base):
  @override  # 型チェッカーでエラー: Base.get_color をオーバーライドしてない
  def get_colour(self) -> str:
    return "red"

これにより、基底クラスのメソッドをオーバーライドするつもりが、実際にはオーバーライドしていなかったというミスを、型チェッカーで発見できるようになります。

エラーメッセージの改善

NameError、SyntaxError、ImportErrorのエラーメッセージが改善されます。

その他の変更点

Python 3.12では今回紹介した4つ以外にも、さまざまな更新があります。

詳細は Python 3公式ドキュメント - What's New In Python 3.12 をご確認ください。

Copyright ©2017- BeProud Inc. All rights reserved.