次のコードサンプルを検討してください。
from typing import Dict, Union
def count_chars(string) -> Dict[str, Union[str, bool, int]]:
result = {} # type: Dict[str, Union[str, bool, int]]
if isinstance(string, str) is False:
result["success"] = False
result["message"] = "Inavlid argument"
else:
result["success"] = True
result["result"] = len(string)
return result
def get_square(integer: int) -> int:
return integer * integer
def validate_str(string: str) -> bool:
check_count = count_chars(string)
if check_count["success"] is False:
print(check_count["message"])
return False
str_len_square = get_square(check_count["result"])
return bool(str_len_square > 42)
result = validate_str("Lorem ipsum")
このコードに対してmypyを実行すると、次のエラーが返されます。
error: Argument 1 to "get_square" has incompatible type "Union[str, bool, int]"; expected "int"
そしてDict[str, Any]
、最初の関数で返された型として使用するか、「TypedDict」mypy拡張機能をインストールせずに、このエラーを回避する方法がわかりません。mypyは実際には「正しい」ですか、私のコードはタイプセーフではありませんか、それともmypyのバグと見なす必要がありますか?
Mypyはここで正しいです-dictの値がstrs、ints、またはboolsである可能性がある場合、厳密に言えば、check_count["result"]
常に正確にintに評価されるとは限りません。
これを解決する方法はいくつかあります。最初の方法は、実際にのタイプをチェックして、check_count["result"]
それがintであるかどうかを確認することです。これは、assertを使用して実行できます。
assert isinstance(check_count["result"], int)
str_len_square = get_square(check_count["result"])
...またはおそらくifステートメント:
if isinstance(check_count["result"], int):
str_len_square = get_square(check_count["result"])
else:
# Throw some kind of exception here?
Mypyは、assertおよびifステートメントでのこの形式の型チェックを理解します(限られた範囲で)。
ただし、これらのチェックをコード全体に分散させるのは面倒な場合があります。したがって、実際にはdictの使用をあきらめて、クラスの使用に切り替えるのが最善かもしれません。
つまり、クラスを定義します。
class Result:
def __init__(self, success: bool, message: str) -> None:
self.success = success
self.message = message
...代わりにそのインスタンスを返します。
これは、最終的にjsonを返す/操作することが目標である場合、このクラスをjsonとの間で変換するコードを記述する必要があるという点で少し不便ですが、型関連のエラーを回避できます。
カスタムクラスの定義は少し面倒になる可能性があるため、代わりにNamedTuple型を使用してみてください。
from typing import NamedTuple
Result = NamedTuple('Result', [('success', bool), ('message', str)])
# Use Result as a regular class
タプル-> jsonコードを記述する必要があり、iircのnamedtuples(collections
モジュールの通常バージョンとこの型付きバリアントの両方)はクラスよりもパフォーマンスが低くなりますが、おそらくそれはユースケースにとって重要ではありません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加