Skip to content

Instantly share code, notes, and snippets.

@9999years
Created July 12, 2021 20:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 9999years/dfefa6a76397576fa32e538a1af65f63 to your computer and use it in GitHub Desktop.
Save 9999years/dfefa6a76397576fa32e538a1af65f63 to your computer and use it in GitHub Desktop.
An unnamed type of map
from dataclasses import dataclass
from typing import Any
from typing import cast
from typing import Dict
from typing import Generic
from typing import Type
from typing import TypeVar
T = TypeVar("T")
@dataclass(frozen=True)
class FooKey(Generic[T]):
"""Key-type of a `FooMap`.
Note that `FooKey` is hashed by identity; even if the fields of two
`FooKey`s are identical, they'll have different hashes, so that they can be
used in the same map.
:param name: The developer-facing name of the key, for debugging.
:param value_type: The type of the value associated with this key.
"""
name: str
value_type: Type[T]
def __hash__(self) -> int:
return super().__hash__()
class FooMap(Dict[FooKey[Any], object]):
"""A `dict` keyed by `FooKey`s.
Useful for sharing a `dict` between modules; by importing the same `FooKey`
instance, any number of modules can predictably access and modify the same
slot in the `dict`.
There are several benefits of this design over picking string key names to
agree on:
* Collisions aren't possible, even if two `FooKey`s have the same ``name``
field, so there aren't namespacing concerns when sharing a `FooMap` across
several (possibly uncooperating) modules.
* Static analysis tools can analyze the keys, so their definitions are easy
to find, refactoring is painless, etc.
* A `FooKey` stores its associated value type, enabling static typechecking
(e.g. with ``mypy``) of heterogeneous `dict`s with dynamic keys. (Compare
with `typing.TypedDict`, which can only support a fixed set of keys.)
Example::
UBOOT_VERSION_CTX = FooKey("UBOOT_VERSION_CTX", str)
context = FooMap()
context[UBOOT_VERSION_CTX] = get_uboot_version()
# In another module:
print('uboot version:', context[UBOOT_VERSION_CTX])
"""
def __getitem__(self, k: FooKey[T]) -> T:
return cast(T, super().__getitem__(k))
def __setitem__(self, k: FooKey[T], v: T) -> None:
return super().__setitem__(k, v)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment