Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use static type checking using Dict with different value types in Python 3.6?

Trying to use static types in Python code, so mypy can help me with some hidden errors. It's quite simple to use with single variables

real_hour: int = lower_hour + hour_iterator

Harder to use it with lists and dictionaries, need to import additional typing library:

from typing import Dict, List
hour_dict: Dict[str, str] = {"test_key": "test_value"}

But the main problem - how to use it with Dicts with different value types, like:

hour_dict = {"test_key": "test_value", "test_keywords": ["test_1","test_2"]}

If I don't use static typing for such dictionaries - mypy shows me errors, like:

len(hour_dict['test_keywords'])
- Argument 1 to "len" has incompatible type

So, my question: how to add static types to such dictionaries? :)

like image 242
sortas Avatar asked Dec 28 '17 19:12

sortas


People also ask

Does Python 3.6 support type hints?

You can add type hints to function/method parameters and return types (Python 3.5), and variables used in assignment (effectively declarations – Python 3.6).

Does Python have static type checking?

Python will always remain a dynamically typed language. However, PEP 484 introduced type hints, which make it possible to also do static type checking of Python code. Unlike how types work in most other statically typed languages, type hints by themselves don't cause Python to enforce types.

Can you specify types in Python?

Python is a strongly-typed dynamic language in which we don't have to specify the data type of the function return value and function argument. It relates type with values instead of names. The only way to specify data of specific types is by providing explicit datatypes while calling the functions.

How does type checking work in Python?

The type checking of the variable type is done at run-time. Also, the type system of the language doesn't force to explicitly declare the 'data-type' of the variable before its usage. The programming languages which are dynamically typed are: Python, Javascript, Ruby, etc.


1 Answers

You need a Union type, of some sort.

from typing import Dict, List, Union

# simple str values
hour_dict: Dict[str, str] = {"test_key": "test_value"}

# more complex values
hour_dict1: Dict[str, Union[str, List[str]]] = {
    "test_key": "test_value", 
    "test_keywords": ["test_1","test_2"]
}

In general, when you need an "either this or that," you need a Union. In this case, your options are str and List[str].

There are several ways to play this out. You might, for example, want to define type names to simplify inline types.

OneOrManyStrings = Union[str, List[str]]

hour_dict2: Dict[str, OneOrManyStrings] = {
    "test_key": "test_value", 
    "test_keywords": ["test_1","test_2"]
}

I might also advise for simplicity, parallelism, and regularity to make all your dict values pure List[str] even if there's only one item. This would allow you to always take the len() of a value, without prior type checking or guard conditions. But those points are nits and tweaks.

like image 67
Jonathan Eunice Avatar answered Sep 20 '22 18:09

Jonathan Eunice