Post

from typing import Dict, Any, Optional

Let's use `typing`.

from typing import Dict, Any, Optional

When working with type hints in Python, we often use Dict, Any, and Optional from the typing module to specify types more clearly. Here’s how they work.

Dict (Dictionary Type Hint)

The Dict[key_type, value_type] syntax is used to define a dictionary where you specify the types of keys and values. In Python, type hints are only for static type checking and do not enforce type restrictions at runtime. This means that even though Dict[str, int] specifies that keys should be strings and values should be integers, Python will not raise a TypeError if an incompatible dictionary is passed.
If you want to manually enforce type checking, you need to validate types inside the function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from typing import Dict, Any

def process_data(data: Dict[str, int]) -> None:
    for key, value in data.items():
        if not isinstance(key, str):
            raise TypeError(f"Invalid key type: {type(key)}. Expected str.")
        if not isinstance(value, int):
            raise TypeError(f"Invalid value type: {type(value)}. Expected int.")
        print(f"{key}: {value}")

sample_data = {"apple": 3, "banana": 5}
process_data(sample_data)  # Works fine

invalid_data = {1: "three"}
process_data(invalid_data)  # TypeError: Invalid key type: <class 'int'>. Expected str.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apple: 3
banana: 5

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[34], line 15
     12 process_data(sample_data)  # Works fine
     14 invalid_data = {1: "three"}
---> 15 process_data(invalid_data)  # Now raises TypeError

Cell In[34], line 6, in process_data(data)
      4 for key, value in data.items():
      5     if not isinstance(key, str):
----> 6         raise TypeError(f"Invalid key type: {type(key)}. Expected str.")
      7     if not isinstance(value, int):
      8         raise TypeError(f"Invalid value type: {type(value)}. Expected int.")

TypeError: Invalid key type: <class 'int'>. Expected str.

Any (Allow Any Type)

The Any type allows any kind of value, meaning it can be of any type.

1
2
3
4
5
6
7
8
from typing import Any  

def print_value(value: Any) -> None:
    print(f"Value: {value}, Type:{type(value)}")  

print_value(123)       # Integer
print_value("hello")   # String
print_value([1, 2, 3]) # List
1
2
3
Value: 123, Type:<class 'int'>
Value: hello, Type:<class 'str'>
Value: [1, 2, 3], Type:<class 'list'>

Optional (Value Can Be None)

Optional[type] means the value can be either the given type or None.
It is equivalent to Union[type, None].

1
2
3
4
5
6
7
8
9
10
from typing import Optional

def greet(name: Optional[str] = None) -> str:
    if name is None:
        return "Hello, Guest!"
    return f"Hello, {name}!"

print(greet())       # Hello, Guest! (when `None` is passed)
print(greet("John")) # Hello, John!

1
2
Hello, Guest!
Hello, John!

Summary

Type HintDescription
Dict[K, V]A dictionary with key type K and value type V
AnyAllows any data type
Optional[T]Allows either T or None

You can combine Dict, Any, and Optional to create more flexible function signatures.

1
2
3
4
5
6
7
8
9
10
11
12
from typing import Dict, Any, Optional

def get_config(settings: Dict[str, Any], key: str) -> Optional[Any]:
    return settings.get(key)

config = {"debug": True, "timeout": 30, "api_key": None}

print(get_config(config, "debug"))   # True
print(get_config(config, "timeout")) # 30
print(get_config(config, "api_key")) # None
print(get_config(config, "unknown")) # None

1
2
3
4
True
30
None
None
This post is licensed under CC BY 4.0 by the author.