7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Intimate MergerAdvent Calendar 2024

Day 6

Python 3.12で型ヒントがもっと便利に!新機能の紹介と活用例

Last updated at Posted at 2024-12-05

はじめに

Pythonは柔軟性と書きやすさ・読みやすさから開発者に人気なプログラミング言語の1つです。
しかし、動的型付け言語であるため、コードが大規模化してくると型に関連するバグや可読性低下などの問題が発生してきます。
こういった型起因の問題を軽減するために役立つのが型ヒント(Type Hint)です。

型ヒントはPython3.5から導入された機能で、コードに型情報を付与することでデータの型を明確するための仕組みです。
静的解析ツールやIDEの機能を使ってバグを早期に発見することができますし、型情報が付与されるため可読性も高まります。

特に近年は型ヒントが進化し、より直感的な記述ができるようになってきています。
本記事では、Python3.12で追加された型ヒントの新機能についていくつか紹介します。

Python3.12で追加された新機能の紹介

1. type構文を使った型エイリアス定義

型エイリアスとは

型エイリアスとは、型情報に名前をつけることです。型エイリアスをつかうことでコードの可読性と再利用性の向上が期待できます。

下記は型エイリアスの基本的な記述例です
変数に型情報を代入します。

# 数値の型エイリアス
Number = int | float

# 座標の型エイリアス
Coordinates = list[tuple(float, float))

⭐️type構文(type statement)

しかし、上記の記述では変数と型エイリアスの判別はぱっと見わかりづらいです。

そこで、Python3.12で追加されたtype構文(type statement)を使って型エイリアスの定義を明示します。

記述は単純に型エイリアス定義の前にtypeをつけるだけです。

type Number = int | float
type Coordinates = list[tuple(float, float))

type構文により型エイリアスの定義であることがわかりやすくなりました。

Python3.10で型エイリアスを明示するためのtyping.TypeAliasが追加されましたが、type文の導入によりtyping.TypeAliasは非推奨になりました。

from typing import TypeAlias

Number: TypeAlias = int | float

2. 型パラメータ構文を使ったジェネリクス

ジェネリクスとは

ジェネリクスは型に依存しない汎用的なコードを記述するための仕組みです。
特定の型に依存せず、さまざまな型を扱う柔軟なクラスや関数を作成することができます。

型変数とは

型変数はジェネリクスを実現するための部品です。
型変数を利用して入力型と出力型が関連付けられた関数やクラスを作成することができます。

typingモジュールのTypeVarを使用して型変数Tを定義します。

from typing import TypeVar

T = TypeVar("T")

ジェネリクスの実装例

下記はPython3.12より前の記述例です

関数の例

下記は型変数を使ったジェネリック(汎用的)な関数の例です。

double_value関数の引数valueと返り値の型に型変数Tを指定します。

from typing import TypeVar

T = TypeVar("T")


def double_value(value: T) -> T:
    return value * 2 


get_value(123)  # => 246
get_value("hello")  # => "hellohello"
クラスの例

クラスの場合はtypingモジュールのGenericを使用して下記のように記述します。

from typing import Generic, TypeVar

T = TypeVar("T")


class A(Generic[T]):
    def __init__(self, value: T) -> None:
        self.value = value

    def get_value(self) -> T:
        return self.value

⭐️型パラメータ構文(type parameter statement)

Python3.12で型パラメータ構文(type parameter statement)が追加されました。

以前は、上述の通りTypeVarを使用して型変数を定義していましたが、型パラメータ構文の導入によりTypeVarを使用せず型変数を定義できるようになりました。

例の関数とクラスを型パラメータ構文で書き換えた記述を下記に示します。

def double_value[T](value: T) -> T:
    return value * 2 
class A[T]:
    def __init__(self, value: T) -> None:
        self.value = value

    def get_value(self) -> T:
        return self.value

TypeVarを使ったジェネリクスの記述よりもシンプルになりました。
型変数Tをグローバル宣言する必要がなくなり、関数・クラス内で完結しているのもいいと思います。

3. メソッドのオーバーライド

⭐️@overrideデコレーター

Python3.12でtyping.overrideが追加されました。
継承元のメソッドを上書きしていることを明示する機能です。

メソッドのオーバーライドすることを表す機能があればなぁと思ってたところ追加されました。

使い方はオーバーライドするメソッドに@overrideデコレーターを付与するだけです。

from typing import override


class Parent:
    def run(self) -> None:
        print("Base")


class Child(Parent):
    @override
    def run(self) -> None:
        print("Child")

単純な例なのであまり有用性を感じないかもしれませんが、規模が大きくなってくると子クラス固有のメソッドとオーバーライドしたメソッドの分別が難しく可読性の低いコードになります。
@overrideを使用することでメソッドがオーバーライドされていることが明示されて可読性が高まります。

まとめ

Python3.12で追加された新機能について紹介しました。

単純なコードであれば型ヒントがなくても十分だと思いますが、コードの規模が大きくなると型起因の問題の発生が考えられます。
規模が大きく型ヒントを利用されてない場合、入力と出力が分かりづらくコードを読むのが大変だと思ったことがあります。

型ヒントを取り入れて、堅牢で保守性の高いコードを目指しましょう!

おわりに

ここまで読んでいただきありがとうございます!
引き続きアドベントカレンダー続きますのでよければ明日以降の記事もご覧ください!

もし弊社インティメート・マージャーに興味があればご覧ください!

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?