Created
July 12, 2021 20:31
-
-
Save 9999years/dfefa6a76397576fa32e538a1af65f63 to your computer and use it in GitHub Desktop.
An unnamed type of map
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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