After Python 3.6, we have typing.NamedTuple
, which is a typed version of collections.namedtuple()
, we can inherit it like a class:
class Employee(NamedTuple):
name: str
id: int
Compared with collections.namedtuple
, this syntax is more beautiful, but I still can't understand its implementation, whether we look at typing.py
file, or do some simple tests, we will find that it is a function rather than a class:
# Python 3.10.6 typing.py
def NamedTuple(typename, fields=None, /, **kwargs):
"""..."""
if fields is None:
fields = kwargs.items()
elif kwargs:
raise TypeError("Either list of fields or keywords"
" can be provided to NamedTuple, not both")
try:
module = sys._getframe(1).f_globals.get('__name__', '__main__')
except (AttributeError, ValueError):
module = None
return _make_nmtuple(typename, fields, module=module)
>>> type(NamedTuple)
<class 'function'>
I understand that it uses some metaclass magic, but I don't understand what happens when using class MyClass(NamedTuple)
. For this reason, I have tried to customize a function to inherit:
>>> def func_for_inherit(*args, **kwargs):
... print(args, kwargs)
...
>>> class Foo(func_for_inherit):
... foo: str
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: function() argument 'code' must be code, not str
Well, this got a result that I can't understand. When inheriting a user-defined function, it seems that its class was called. What happened behind this?
collections.namedtuple
is also a function – Cletisclass Whatever(collections.namedtuple):
and have that work. – Monjocollections.namedtuple
as a factory; while I see thetyping.NamedTuple
as a class that the said factory generates (or an instance of it). I know that this is not technically true, but that's how my brain is dealing with ignorance :) – Cletis