Reputation: 381
I am trying to build a typed dictionary class, similar to NamedTuple
but with the ability to subclass said tuples. Unfortunately, I find that in the base constructor where I want enforce types, I do not have access to the type annotations of subclasses.
Here's a minimal example:
class TypedDict:
def __init__(self, **kwargs):
print(self.__annotations__)
for k, v in kwargs.items():
# Check if k is in self.__annotations__
# Check that v has the same type as self.__annotations__[k]
pass
class A(TypedDict):
field_a: int = 3
class B(A):
field_b: int = 3
And on the console:
>>> a = A()
{'field_a': <class 'int'>}
>> b = B()
{'field_b': <class 'int'>} # Where is 'field_a'?
How do I get the constructor in TypedDict.__init__
to also see the annotations of A
?
Upvotes: 0
Views: 1128
Reputation: 381
Ah, I have a workaround solution using the class mro
.
class TypedDict:
def __init__(self, **kwargs):
annotations = {}
for cls in self.__class__.mro():
# __annotations__ is only present when the class has defined annotations.
annotations.update(getattr(cls, "__annotations__", {}))
print(annotations)
for k, v in kwargs.items():
# Check if k is in self.__annotations__
# Check that v has the same type as self.__annotations__[k]
pass
class A(TypedDict):
field_a: int = 3
class B(A):
field_b: int = 3
On the console:
>>> a = A()
{'field_a': <class 'int'>}
>> b = B()
{'field_a': <class 'int'>, 'field_b': <class 'int'>}
Upvotes: 0
Reputation: 281748
You're looking for typing.get_type_hints
, not __annotations__
. typing.get_type_hints
will merge the annotations of all classes in the MRO, as well as resolving string annotations.
type_hints = typing.get_type_hints(type(self))
Upvotes: 3