Search code examples
pythonnamedtuplepython-collections

What's the first argument of namedtuple used for?


We use namedtuple like this:

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p=Point(1,2)
>>> p.x
1

I found the first argument of namedtuple seems useless, since:

Firstly, we can not use it (to create an instance, for example):

>>> from collections import namedtuple
>>> P = namedtuple('Point', ['x', 'y'])
>>> p = Point(1,2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Point' is not defined

Secondly, there seems no constraint for it (for example, we don't have to make it unique):

>>> P1 = namedtuple('Point', ['x', 'y'])
>>> P2 = namedtuple('Point', ['x', 'y', 'z'])
>>> p1 = P1(1,2)
>>> p2 = P2(1,2,3)
>>> p1
Point(x=1, y=2)
>>> p2
Point(x=1, y=2, z=3)

I did not find a explanation from the manual or by googling. There is a relevant question here, but it did not answer why namedtuple need the first argument and how it can be used or when it's necessary.


Solution

  • It sets the name of the generated class:

    >>> from collections import namedtuple
    >>> Point = namedtuple('Point', ['x', 'y'])
    >>> Point
    <class '__main__.Point'>
    >>> Point = namedtuple('Foobar', ['x', 'y'])
    >>> Point
    <class '__main__.Foobar'>
    

    The Point name in your globals is just a reference to the generated class, the class itself needs to have a name. The name cannot be taken from the variable to which the object is assigned, because the class is generated first and only then assigned in a separate step (after the namedtuple() call returns).

    It doesn't need to be unique in the same way that a class name doesn't need to be unique when using class:

    >>> class Foo(object):
    ...     pass
    ... 
    >>> Bar = Foo
    >>> class Foo(object):
    ...     pass
    ... 
    >>> Bar
    <class '__main__.Foo'>
    >>> Foo
    <class '__main__.Foo'>
    

    You usually avoid that kind of thing by keeping names unique per module, but you don't have to.

    The name is there for debugging purposes; in tracebacks and in repr() output the name is shown to help you figure out what class is used.

    To Python, it doesn't matter if the generated class reuses a name. It does to the pickle module; if you need to be able to pickle your named tuple class instances, make sure you pick a name that matches the global by which pickle can later load it again. But if re-using a name makes sense to you or doesn't actively hinder your code development or debugging tasks, then by all means, reuse the name or pick anything you like.