namedtuple or NamedTuple?

      No Comments on namedtuple or NamedTuple?

The Problem

Many of you are probably familiar with namedtuple (and if not, you should).
However, in this age of type-hints (if you don’t know what it is, you should 😉 ), namedtuple is proving less useful.

Consider the following code:

def expect_str(str_arg):
    # type: (typing.Text) -> None

def expect_int(num_arg):
    # type: (int) -> None

ItemCount = collections.namedtuple('ItemCount', ['name', 'count'])

item_count = ItemCount('aaa', 42)
item_count = ItemCount(11, 42)

When asking PyCharm what is the type of in line 14 we get:

PyCharm intellisense for unhinted named tuple

But on line 16, the type is already int:

At this point, PyCharm will complain that expect_str function expects a string:

The worse news is that mypy is not even catching this, because namedtuples are simply untyped, so is of type Any (when using mypy utilize reveal_type to understand deductions).

All of that is rather icky if you ask me. I get that Python is dynamic and all, but same class having totally unexpected types is hard to work with, and the fact PyCharm’s intelli-sense keeps changing its mind is confusing. I preferred it being treated the same as mypy.

BTW, If you add a method that expects ItemCount, the deduced type within that function, is indeed Any. Try it!


With typing.NamedTuple you can easily define the types for your tuple components:

from typing import Text, NamedTuple

TypedItemCount = NamedTuple('TypedItemCount', 
                            [('name', Text), ('count', int)])

typed_item_count = TypedItemCount('abc', 42)

no_good_item_count = TypedItemCount(24, 42)

Now we get the warning at the point we really should:

And with mypy:

[email protected]:$ mypy error: Argument 1 to "TypedItemCount" has 
    incompatible type "int"; expected "str"

Found 1 error in 1 file (checked 1 source file)


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.