Python の型ヒントでは、値に特定の属性があることをどのように要求すればよいでしょうか? 質問する

Python の型ヒントでは、値に特定の属性があることをどのように要求すればよいでしょうか? 質問する

次のような単純な関数があるとします。

def foo(a: Any):
    return a.bar + a.baz

Any型ヒントを、型であることを考慮すると、要求するもの(つまり、提案するもの)に変更したいと思います。ヒント) は、および属性をa提供します。これを何に変更すればよいでしょうか?barbaz

ベストアンサー1

これはまさにプロトコル簡単に言えば、プロトコルを使用すると構造的なの代わりに名目上のサブタイプ化。名目上のサブタイプ化では、型 A が B を明示的に継承または拡張する場合、型 A は B のサブタイプになります。構造的なサブタイプ化では、型 A が B と同じメソッドと属性の「シグネチャ」を持つ場合、型 A は B のサブタイプになります (いくつかの制限あり)。

例えば:

# If you're using Python 3.8+
from typing import Protocol

# If you need to support older versions of Python,
# pip-install the 'typing_extensions' module and do:
from typing_extensions import Protocol

class SupportsBarBaz(Protocol):
    bar: int
    baz: int

class MyUnrelatedClass1:
    def __init__(self, bar: int, baz: int) -> None:
        self.bar = bar
        self.baz = baz

class MyUnrelatedClass2:
    def __init__(self, bar: int, baz: int, blah: str) -> None:
        self.bar = bar
        self.baz = baz
        self.blah = blah

class MyUnrelatedClass3:
    def __init__(self, bar: str, baz: str, blah: str) -> None:
        self.bar = bar
        self.baz = baz
        self.blah = blah

def foo(a: SupportsBarBaz) -> int:
    return a.bar + a.baz

# These both type-check, even though there's no explicit relationship
# between 'SupportsBarBaz' and these two classes
foo(MyUnrelatedClass1(1, 2))
foo(MyUnrelatedClass2(1, 2, "abc"))

# But this doesn't type-check, since 'bar' and 'baz' are both strs here
foo(MyUnrelatedClass3("a", "b", "c"))

プロトコルの使用に関する詳細は、mypy ドキュメントそのページの情報はすべて PEP に準拠しているため、他の型チェッカーが独自のプロトコル サポートの実装を完了していれば、そこに記載されている情報はすべて他の型チェッカーにも適用されるはずです。

プロトコルを使ったもう少し複雑な例も以下で見つけることができます。typeshed、Python 標準ライブラリの型ヒントのリポジトリ

ただし、これはすべて、コード内で静的分析を実際に使用する場合のみ重要だと思います。そうでない場合は、もっと簡単な方法で、 にカスタム型エイリアスを定義し、Anyそのエイリアスが「想定される」意味を文書化し、本格的なプロトコルの代わりにそのエイリアスを使用することができます。そのエイリアスは、静的分析/自動補完ツールなどの目的ではほとんど役に立たないでしょうが、人間は通常、コメントを読むのに問題はありません。

おすすめ記事