次のような単純な関数があるとします。
def foo(a: Any):
return a.bar + a.baz
Any
型ヒントを、型であることを考慮すると、要求するもの(つまり、提案するもの)に変更したいと思います。ヒント) は、および属性をa
提供します。これを何に変更すればよいでしょうか?bar
baz
ベストアンサー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
そのエイリアスが「想定される」意味を文書化し、本格的なプロトコルの代わりにそのエイリアスを使用することができます。そのエイリアスは、静的分析/自動補完ツールなどの目的ではほとんど役に立たないでしょうが、人間は通常、コメントを読むのに問題はありません。