Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What type represents typing.Any except None? [duplicate]

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

like image 935
Yam Mesicka Avatar asked Sep 09 '19 13:09

Yam Mesicka


People also ask

What is type any in Python?

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.

What are type hints?

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.

What is optional in Python typing?

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!

What kind of errors can type annotations potentially prevent Python?

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.


2 Answers

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*]'

like image 96
Jarno Avatar answered Sep 27 '22 07:09

Jarno


Python type hinting can't exclude types. You can't exclude Nones, strs 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.

like image 38
vurmux Avatar answered Sep 27 '22 07:09

vurmux