Last active
May 7, 2024 16:05
-
-
Save MarcinKonowalczyk/afd1f7ec9e22686e6c3b347f94a1217e to your computer and use it in GitHub Desktop.
generic namedtuple
This file contains 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 typing import TYPE_CHECKING, TypeVar, Generic, Tuple | |
from typing_extensions import reveal_type | |
T1 = TypeVar("T1") | |
T2 = TypeVar("T2") | |
if TYPE_CHECKING: | |
# This is how Group looks like to the type checker | |
class Group(Tuple[T1, T2], Generic[T1, T2]): | |
def __new__(cls, key: T1, group: T2) -> "Group[T1, T2]": ... | |
@property | |
def key(self) -> T1: ... | |
@property | |
def group(self) -> T2: ... | |
else: | |
# This is the actual implementation of Group, aka literally a tuple with two boltons | |
class Group(tuple): | |
def __new__(cls, key, group): | |
return tuple.__new__(cls, (key, group)) | |
@property | |
def key(self): | |
return self[0] | |
@property | |
def group(self): | |
return self[1] | |
# Can unpack/index the Group because its literally a tuple at runtime | |
G1 = Group(1, "hello") | |
key1, grp1 = G1 | |
key1 = G1[0] | |
grp1 = G1[1] | |
key1 = G1.key | |
grp1 = G1.group | |
# Types are ok | |
if TYPE_CHECKING: | |
reveal_type(key1) # Revealed type is "builtins.int" | |
reveal_type(grp1) # Revealed type is "builtins.str" | |
reveal_type(G1.key) # Revealed type is "builtins.int" | |
reveal_type(G1.group) # Revealed type is "builtins.str" | |
reveal_type(G1[0]) # Revealed type is "builtins.int" | |
reveal_type(G1[1]) # Revealed type is "builtins.str" | |
# And it *is* a generic | |
G2 = Group(False, 1.0) | |
key2, msg2 = G2 | |
if TYPE_CHECKING: | |
reveal_type(key2) # Revealed type is "builtins.bool" | |
reveal_type(msg2) # Revealed type is "builtins.float" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment