22

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.

Community
  • 1
  • 1
WKPlus
  • 6,955
  • 2
  • 35
  • 53

1 Answers1

20

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.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • But when I define two named tuple with the same name, it works fine, why? – WKPlus May 29 '15 at 09:38
  • @WKPlus why *wouldn't* it? – jonrsharpe May 29 '15 at 09:39
  • @WKPlus: I can create multiple classes with the same name too. Or functions. For debugging purposes and clarity you want to keep them unique, but it is not enforced. – Martijn Pieters May 29 '15 at 09:40
  • Two named tuples with the same name but contain different attributes, it still can work, does this make sense? – WKPlus May 29 '15 at 09:42
  • @WKPlus: if to you as a developer it doesn't make sense, then don't use duplicate names. But in some circumstances it is easy enough to generate named tuple classes on demand and the name *doesn't matter*, so generating new unique names for each doesn't make sense either. – Martijn Pieters May 29 '15 at 09:43
  • @WKPlus: but usually *nothing breaks* when you reuse a name. If you want to pickle instances of the named tuple class, you need to have a name that matches the global by which you store it (so unpickling can find the class again), but on the whole, Python **doesn't care**. – Martijn Pieters May 29 '15 at 09:44
  • "The name is there for debugging purposes;To Python, it doesn't matter if the generated class reuses a name", this enhances my understanding:) – WKPlus May 29 '15 at 09:52