Last active
July 6, 2023 11:47
-
-
Save TheArcherST/fd9d924323de6e50cc7794d4a67fffd7 to your computer and use it in GitHub Desktop.
Python namedtuple, but a base class.
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
# https://gist.github.com/TheArcherST/fd9d924323de6e50cc7794d4a67fffd7 | |
from typing import ClassVar, Type | |
from collections import namedtuple | |
from itertools import chain | |
class Namedtuple( | |
tuple # for IDE typechecker | |
): | |
"""Namedtuple base class | |
Allows to create namedtuple with explicitly defined fields, | |
to allow IDE like PuCharm infer field names and their types. | |
Example | |
------- | |
>>> from typing import Generic, TypeVar | |
>>> from numbers import Number | |
... | |
>>> _T = TypeVar("_T", bound=Number) | |
... | |
>>> class Coordinates2D(Namedtuple, Generic[_T]): | |
... x: _T | |
... y: _T | |
... | |
>>> class Coordinates3D(Coordinates2D[_T]): | |
... z: _T | |
... | |
>>> coord = Coordinates3D(1, 2, 3) | |
>>> print(coord) | |
Coordinates3D(x=1, y=2, z=3) | |
>>> print(coord.x) | |
1 | |
""" | |
__tp: ClassVar[Type[tuple]] | |
def __init_subclass__(cls, **kwargs): | |
cls.__tp = namedtuple( | |
cls.__name__, | |
chain.from_iterable( | |
filter(lambda x: not x.startswith("_" + i.__name__), | |
getattr(i, "__annotations__", {})) | |
for i in reversed(cls.__mro__) | |
), | |
) | |
def __new__(cls, *args, **kwargs): | |
return cls.__tp(*args, **kwargs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment