I wrote the following function:
def _clean_dict(d):
return {k: v for k, v in d.items() if v is not None}
I want to add type annotations to the function:
def _clean_dict(d: Dict[Any, Any]) -> Dict[Any, Any]:
return {k: v for k, v in d.items() if v is not None}
However, I want to explicitly define that the values inside the returned dictionary cannot be None.
Is there a way to say "Any
type, except NoneType
" or "Every possible value but None
"?
Python any() FunctionThe any() function returns True if any item in an iterable are true, otherwise it returns False. If the iterable object is empty, the any() function will return False.
PEP 484 introduced type hints — a way to make Python feel statically typed. While type hints can help structure your projects better, they are just that — hints — and by default do not affect the runtime.
Use Optional to indicate that an object is either one given type or None . For example: from typing import Dict, Optional, Union dict_of_users: Dict[int, Union[int,str]] = { 1: "Jerome", 2: "Lewis", 3: 32 } user_id: Optional[int] user_id = None # valid user_id = 3 # also vald user_id = "Hello" # not valid!
Idiomatic use of type annotations can sometimes run up against what a given version of Python considers legal code. These can result in some of the following errors when trying to run your code: ImportError from circular imports. NameError: name "X" is not defined from forward references.
Given that you are willing to fix the types of keys and values when the function is called you can use generics to make this explicit. This still potentially allows instances of V
to be None
, but it makes the intent pretty clear. Note that you have to use Mapping
because of variance issues. However, this is preferable anyway.
from typing import *
K = TypeVar("K")
V = TypeVar("V")
def _clean_dict(d: Mapping[K, Optional[V]]) -> MutableMapping[K, V]:
return {k: v for k, v in d.items() if v is not None}
With this definition mypy
correctly turns optional into non-optional types.
# clean_dict.py
d = {"a": 1, "b": 2, "c": None}
reveal_type(d)
reveal_type(_clean_dict(d))
$ mypy clean_dict.py
note: Revealed type is 'builtins.dict[builtins.str*, Union[builtins.int, None]]'
note: Revealed type is 'typing.MutableMapping[builtins.str*, builtins.int*]'
Python type hinting can't exclude types. You can't exclude None
s, str
s or any another type.
The only thing you can use to try to emulate None
exclusion is to use Union and write every type you are actually using in the dictionary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With