Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specify keys for mypy in python dictionary

Suppose I have some code like

def get_x(d: dict) -> int:
    d["x"]

However, I want to tell mypy that d should only contain certain keys (only the "x" key for example). That way, if I make a mistake lower in the code trying to reference an invalid key of d, mypy will trigger an error.

My question is:

  1. Is this possible? Can mypy validate dictionary keys?
  2. If yes, how is this done? If no, is there a preferred workaround?
like image 383
Daniel Kats Avatar asked Feb 02 '19 03:02

Daniel Kats


People also ask

Can Python dictionary keys be set?

In Python, the keys() and items() methods of dictionaries dict can be used to perform set operations on keys and key-value pairs. For example, you can generate a dictionary consisting of elements (keys and values) common to multiple dictionaries.

Can I use float as dictionary key?

For example, you can use an integer, float, string, or Boolean as a dictionary key. However, neither a list nor another dictionary can serve as a dictionary key, because lists and dictionaries are mutable.

Can strings be keys in dictionary?

The keys of a dictionary can be any kind of immutable type, which includes: strings, numbers, and tuples: mydict = {"hello": "world", 0: "a", 1: "b", "2": "not a number" (1, 2, 3): "a tuple!"}


1 Answers

Ran into this problem too when trying to put some typing around AWS API Gateway/Lambda integration.

As pointed out by @Michael0x2a in the comments, TypedDict would seem to be the way to go, especially because it does not require any conversions yourself before passing into a function (a requirement for API responses, like you mentioned).

from mypy_extensions import TypedDict

DictWithOnlyX = TypedDict('DictWithOnlyX', {"x": str})

# error: Extra key 'y' for TypedDict "DictWithOnlyX@58"
dx1: DictWithOnlyX = { "y": 123 }

# error: Incompatible types (expression has type "int",
#        TypedDict item "x" has type "str")
dx2: DictWithOnlyX = { "x": 123 }

# GOOD!
dx3: DictWithOnlyX = { "x": "123" }

Should also note that, if dependencies are segregated between production and dev/test, then this makes mypy a production dependency.

like image 133
kevlarr Avatar answered Oct 11 '22 23:10

kevlarr