Let's consider an instance check for dict_keys
type :
dict_keys = type({}.keys())
print(dict_keys) # <class 'dict_keys'>
assert isinstance({}.keys(), dict_keys)
According to Python documentation .keys()
, .values()
and .items()
all return a dictionary view which is codified in documentation as dictview
view objects. However there seems to be no dictview
type at least not in cPython implementation:
# same output across Python 3.7 - 3.11
print(dict_keys.mro()) # [<class 'dict_keys'>, <class 'object'>]
print({}.values().__class__.mro()) # [<class 'dict_values'>, <class 'object'>]
print({}.items().__class__.mro()) # [<class 'dict_items'>, <class 'object'>]
I have a use case where I need to accept native dictview
but reject user-provided objects which quack like dictview
(duck-typing is not an option by design). I can do this by separately checking for dict_keys
, dict_values
and dict_items
, but mypy complains on:
dict_keys = type({}.keys())
# main.py:1: error: Need type annotation for "dict_keys" [var-annotated]
A closest exposed type is types.MappingProxyType
which allows for user-created dict views. It is not perfect because it has some extra methods mapping
, but close enough. However, it does not work either:
from types import MappingProxyType
from typing import Type
dict_keys: Type[MappingProxyType] = type({}.keys()) # error: Incompatible types in
# assignment (expression has type "Type[dict_keys[<nothing>, <nothing>]]",
# variable has type "Type[MappingProxyType[Any, Any]]") [assignment]
x: dict_keys # error: Variable "__main__.dict_keys" is not valid as a type [valid-type]
len(x)
The first error shows that mypy is pretty well aware of dict_keys
existence, but it still insists that I should manually annotate it.
The second error is not related to my core question (it is discussed in mypy "is not valid as a type" for types constructed with `type()`). mypy playground.
Is there an obvious solution that I am missing, or should I head to mypy repo and open an issue? Of course I could just use Any
but this is not the kind of solution I am looking for.