タイピングの定義の違い。Dictとdict?


105

Python3.5で型ヒントを使用して練習しています。私の同僚の1人が使用していますtyping.Dict

import typing


def change_bandwidths(new_bandwidths: typing.Dict,
                      user_id: int,
                      user_name: str) -> bool:
    print(new_bandwidths, user_id, user_name)
    return False


def my_change_bandwidths(new_bandwidths: dict,
                         user_id: int,
                         user_name: str) ->bool:
    print(new_bandwidths, user_id, user_name)
    return True


def main():
    my_id, my_name = 23, "Tiras"
    simple_dict = {"Hello": "Moon"}
    change_bandwidths(simple_dict, my_id, my_name)
    new_dict = {"new": "energy source"}
    my_change_bandwidths(new_dict, my_id, my_name)

if __name__ == "__main__":
    main()

どちらも問題なく動作し、違いはないようです。

typingモジュールのドキュメントを読みました。

typing.Dictまたはdictその1私は、プログラムで使用する必要がありますか?


11
Pythonは実際には型ヒントを強制しないことに注意してください。これらは単なるヒントであり、型を強制するために実行時やコンパイル時にも使用されません。Pythonは強く型付けされる場合があり(弱い型付けの反対)、動的に型付けされることもあります(厳密な型付けの反対)。Pythonは強く型付けされていますか?を参照してください。mypyのような外部ツールは、静的分析と呼ばれるプロセスで、これらのヒントを使用してより良いコードを書くのに役立ちます。
MartijnPieters

1
@MartijnPieters MyPyと一緒にコードで型ヒントを使用し、型安全性を備えたPythonを使用できるふりをするのが大好きでした。残念ながら、A)3.4未満では機能しないコード、B)どうやらタイプヒントは笑いものであるため、人々が私を笑わせてしまいました。本当に残念です。

3
@cat:タイプヒントはFacebookの従業員によってPythonに導入されました。これは、同じ機能をPHPに追加することに大きな成功を収めたためです(ハックを参照)。笑っている人は、一握りのエンジニア以上で大きなプロジェクトを構築したことはありません。
MartijnPieters

3
@MartijnPietersいいえ、def a(b: int) -> bool:Python 2.7の構文エラーであり、古いバージョンのPython3でも構文エラーだと思います。

1
@cat:ここでは、Python3.0に追加された構文である関数アノテーションについて話しています。したがって、それが構文エラーである唯一のバージョンは2.7です。これが、mypyがその情報をコメントに入れることをサポートしている理由です。
MartijnPieters

回答:


147

プレーンtyping.Dictを使用することとdict、いいえを使用することの間に実際の違いはありません。

ただし、これtyping.Dictジェネリック型 *であり、キーと値の型も指定できるため、柔軟性が高くなります。

def change_bandwidths(new_bandwidths: typing.Dict[str, str],
                      user_id: int,
                      user_name: str) -> bool:

このように、それはよくあなたのプロジェクトの生涯の中でいくつかの点であなたが拡大している時点で、もう少し正確に辞書引きを定義することが考えtyping.Dicttyping.Dict[key_type, value_type]置き換えるよりも「小さい」の変化ですdict

ここでMappingまたはMutableMappingタイプを使用すると、これをさらに一般的にすることができます。関数はマッピングを変更する必要がないので、私はに固執しMappingます。Adictは1つのマッピングですが、マッピングインターフェイスを満たす他のオブジェクトを作成することもでき、関数はそれらで引き続き機能する可能性があります。

def change_bandwidths(new_bandwidths: typing.Mapping[str, str],
                      user_id: int,
                      user_name: str) -> bool:

これで、この関数の他のユーザーに、コードが渡されたマッピングを実際に変更しないことを明確に伝えていますnew_bandwidths

実際の実装は、印刷可能なオブジェクトを期待しているだけです。これはテスト実装かもしれませんが、new_bandwidths: typing.AnyPythonのオブジェクトはすべて印刷可能であるため、現状では、を使用した場合でもコードは引き続き機能します。


*:注:Python 3.7以降を使用しdictている場合、モジュールをfrom __future__ import annotationsで開始するとジェネリック型として使用できます。Python3.9以降dict(および他の標準コンテナー)は、それがなくてもジェネリック型としての使用をサポートしています。ディレクティブ


2
有用な追加の例は、辞書の値が異なるタイプである可能性がある場合です。たとえば{"name": "bob", "age" : 51}、次のようになりtyping.Mapping[Union[str, int]ますか?どのようなネストされた辞書についての{"person": {"name":"bob", "age": 51}ようなものになることでしょうかtyping.Mapping[str, typing.Mapping[Union[str, int]]Unionそのように使用すると、順序がないため厳密なスキーマではないため、問題が発生します。多分それは大丈夫ですか、それとも代替手段がありますか?
ダボス

1
Unionまだオープンディスカッションだと思う質問については気にしないでくださいgithub.com/python/typing/issues/28–
Davos

1
これは非常に興味深く、有用で、関連しているようですpython.org/dev/peps/pep-0589
GregHilston19年

@GregHilston:これは、実際には、辞書に含めることができるキーを制限し、関連付けられた各値に含める必要のあるタイプを指定する方法についてです。
MartijnPieters

1
@GregHilston:ああ、そうです。
MartijnPieters

26

typing.Dictの汎用バージョンですdict

class typing.Dict(dict, MutableMapping[KT, VT])

dictの汎用バージョン。このタイプの使用法は次のとおりです。

def get_position_in_index(word_list: Dict[str, int], word: str) -> int:
     return word_list[word]

ここで、dictのキーと値のタイプを指定できます。 Dict[str, int]

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.