558 views
B!0X

PythonとNewType

python-newtype

はじめに

この記事では、Pythonにおける NewType テクニックを紹介します。このテクニックを使用すると、型による値の確からしさを保証しながら、ランタイムにおけるオーバーヘッドを限りなくゼロに近づけることができます。

問題設定

アプリケーションを静的型などを用いてなるべく堅牢に記述するためには、単なる値に対しても専用の型を用意して値の確からしさを静的にチェックさせることがよくあります。

class UserId(int):
    pass

def get_user_by_id(user_id: UserId) -> ...:
    ...

get_user_by_id(UserId(1)) # OK
get_user_by_id(1)  # 型エラー

このような実装により、プリミティブとしては一緒の他の int 型の値の混入を防ぐことができます。ただし、この方法の問題点は、値の確かさを静的にチェックさせるための代償として、ランタイムに実際のオブジェクトが作成されるため、オーバーヘッドが発生することです。

NewTypeの使い方

Pythonのtypingモジュールには NewType という関数が用意されており、これを使用することで静的チェックの恩恵を受けつつ、ランタイムのオーバーヘッドを限りなく減らすことができます。

from typing import NewType

UserId = NewType("UserId", int)

def get_user_by_id(user_id: UserId) -> ...:
    ...

get_user_by_id(UserId(1))
get_user_by_id(1)  # 型エラー

UserId("id")  # 型エラー

このように、実際にクラスを用いて専用の型を用意していた場合と同様に、型による恩恵を受けることができます。また、実行時のオーバーヘッドをなくしている方法についても見ていきましょう。

NewTypeの実装

def NewType(name, tp):
    def new_type(x):
        return x

    new_type.__name__ = name
    new_type.__supertype__ = tp
    return new_type

NewType 関数自体は、ローカルスコープ内で new_type という関数を定義し、その関数を return しています。つまり、 UserId = NewType("UserId", int) のように宣言した型は、実際にはただの関数であるということです。また、その関数の挙動は単純に入力された値をそのまま return しているだけです。

具体的には以下のようになります。

def new_type(x):
    return x

UserId = new_type

これにより、 UserId(1) は実際にはただの値を使っているのと同じです。

UserId(1) = new_type(1) = 1

このようにして、実行時のオーバーヘッドをなるべく減らしているということです。NewType が行っている __name__ や __supertype__ の代入は、あくまでも型チェックに必要な名前やスーパータイプを設定しているだけです。

このようにして、 NewType は実行時のオーバーヘッドをなるべく減らしつつ、静的型による恩恵を受けることを可能にしています。

関連事例

  • データ分析支援

    事例:過去実績を提案に活用する分析の仕組み

    広告代理店との取り組みです。同社は過去実績の示唆を次の提案へ反映し、結果をどのように予測したか、その背景まで提案先のクライアントへ説明できるようになりました。KDOT は案ごとの見込みと判断材料を比較できる仕組みを業務アプリとして実装しました。さらに業務アプリの中核となる処理ロジックと機械学習モデルについて、特許手続きを担う弁理士が技術の新規性や工夫を検討するための資料を作成しました。その後この発明には特許が付与されました。

  • データ基盤構築 / 技術顧問(技術企業向け)

    事例:効果検証の分析処理基盤

    効果検証を提供する分析会社との取り組みです。同社は分析者の人数に比例してしか売上と利益を伸ばせない事業の形を、効果検証をプロダクトとして提供することで変革しようとしていました。手法とモデルは同社のまま、社内では開発できなかった、データと機械学習の重い推定を製品として動かす仕組みの開発を、開発支援会社の KDOT に任せました。推定を案件ごとの手作業ではなくシステムで実行できるようになったことで、同社は人数に比例しない形で売上と利益を伸ばすことを目指せるようになりました。

開発の相談先をお探しですか。

この記事に関わることについてご相談がある方はお問い合わせください。

KDOT についてお問い合わせ