2017-05-15 10 views
1

は、コードサンプルを、次の点を考慮使用したにもかかわらず:mypyエラー - 互換性のない型 '連合

error: Argument 1 to "get_square" has incompatible type "Union[str, bool, int]"; expected "int" 

と私はわからない:このコードに対してmypyを実行する場合

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") 

、次のエラーが返されます最初の関数で返される型としてDict[str, Any]を使用せずにこのエラーを回避する方法、または 'TypedDict' mypy拡張をインストールする方法。 mypyは実際には「正しい」ですか、私のコードはタイプセーフではありませんか、これはmypyのバグと見なされるべきですか?

答えて

1

あなたのdictの値がstrs、ints、またはboolの場合、厳密に言えば、check_count["result"]は常に正確にintと評価されるとは仮定できません。

解決方法はいくつかあります。最初の方法は、実際にはのタイプをcheck_count["result"]にチェックしてintであるかどうかを確認することです。

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は(限られた範囲)をアサートし、if文では、このフォームのチェックを入力し理解しています。

ただし、コード全体でこれらのチェックがばらばらになることがあります。だから、実際にはdictsの使用をあきらめて、クラスを使うように切り替えるのがベストかもしれません。

クラスを定義し、次のとおりです。

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モジュールとこの型付きバリアントから)は、クラスのパフォーマンスがあまり良くありませんが、おそらくそれはあなたのユースケースに関係なくありません。

+0

あなたは本当のマイパイの専門家マイケルです、多くの感謝! –

関連する問題