1

I have used collections.namedtuple in some code, but now I see that in Python 3.6 there is a new typing.NamedTuple base class available in the new class style. It also appears to make type hints available for the named indexes in the tuple.

Is there any reason to continue using the older collections.namedtuple (from Python 2.6) in newly written code, beyond compatibility with older code?

i.e. Is there a performance advantage, does it use less memory, etc.?

LightCC
  • 9,804
  • 5
  • 52
  • 92
  • No, it basically wraps `collections.namedtuple` anyway, although it does use some confusing metaclass magic to accomplish this, which makes some things act sort of weird. See [this question](https://stackoverflow.com/questions/60707607/weird-mro-result-when-inheriting-directly-from-typing-namedtuple) for example – juanpa.arrivillaga May 07 '20 at 02:52
  • So, to be explicit, you might think if you create a class, `Foo(NamedTuple)` and then instantiate an object, `foo = Foo(bar, baz)`, that `isinstance(foo, NamedTuple)` would be True, but it isn't... Of course, this is symmetric with `isinstance(foo, collections.namedtuple)` but basically, it is more obvious thate `namedtuple` is a class factory, whereas `NamedTuple` essentially uses the metaclass machinery to act as a call factory without being a proper parent class itself. But practicality beats purity. – juanpa.arrivillaga May 07 '20 at 02:55
  • @juanpa.arrivillaga You could convert that into an answer... It seems pretty thorough. :) – LightCC May 07 '20 at 18:27

1 Answers1

1

Unfortunately, typing.NamedTuple does not currently support mixins. So for example (snipping the example below from this issue discussion) we can create an enum that inherits all of the properties from the collections.namedtuple mixin, but we can't do the same with typing.NamedTuple which we might desire in order to gain the type hints for free:

>>> from enum import Enum
>>> from collections import namedtuple
>>> TTuple = namedtuple('TTuple', 'id a blist')
>>> class NTEnum(TTuple, Enum):
...     NONE = TTuple(0, 0, [])
...     A = TTuple(1, 2, [4])
...     B = TTuple(2, 4, [0, 1, 2])
... 
>>> NTEnum.A
<NTEnum.A: TTuple(id=1, a=2, blist=[4])>
>>> 
>>> NTEnum.A.id
1
>>> NTEnum.B.blist
[0, 1, 2]