1

this is my first question on stackoverflow. I just learnt the namedtuple and found sth weird.

When you want to initiate a namedtuple from an iterable, you have to either add a prefix * or use the _make method.

for instance:

City=namedtuple('city',['name','country','population','coordinates'])

delhi_data = ('Delhi NCR', 'IN', 21.935, LatLong(28.613889, 77.208889))

delhi = City(*('Delhi NCR', 'IN', 21.935, LatLong(28.613889, 77.208889)))

But when you initiate a tuple, dict or even orderedDict from the same collection package, you can just tuple() or dict() or orderedDict().

for instance:

from collections import OrderedDict

items = (
('A', 1),
('B', 2),
('C', 3)
)

regular_dict = dict(items)

ordered_dict = OrderedDict(items)

Why the syntax for namedtuple is so weird? Thanks!

jijijude
  • 23
  • 4

2 Answers2

2

You can see some discussion here about why namedtuple was designed this way. The basic reason is that the "normal" way to create a namedtuple is with a call like MyTupleClass(1, 2, 3), where the values are accepted as separate arguments. If it accepted only one iterable argument (as tuple does), you would have to write MyTupleClass((1, 2, 3)) with an extra set of parentheses (that is, MyTupleClass(1, 2, 3) would raise an error, as tuple(1, 2, 3) does). It is true that this means you have to use an extra star (or use the ._make() method) if initializing from an iterable, but this isn't any harder, it's just different. The decision was apparently to make the simple case (initializing with literal values) easier, at the expense of making a more complex case (unpacking from an iterable) a bit different from a regular tuple.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • Yes! Could I summarize your point like this: tuple take one argument and namedtuple take multi-argument accordingly, so the * just to unpack the item to match each argument in the nametuple. Btw, the OrderedDict Object also take only one argument? Thanks! – jijijude Jan 25 '17 at 08:36
  • I have just tried it out. The OrderDict get at most 1 argument like tuple. Thanks for the help! – jijijude Jan 25 '17 at 08:42
1

From your example, it behaves similarly to a dict:

from collections import namedtuple
MyTuple = namedtuple('MyTuple', 'A B C')

items = (('A', 1), ('B', 2), ('C', 3))

my_tuple = MyTuple(**dict(items))
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
  • Thanks for the example! Sorry but I am now more confused. Why double ** here? I am new to python... – jijijude Jan 25 '17 at 08:03
  • `**` says to map the key value pairs of the dict into the MyTuple constructor. You should read the [link](http://stackoverflow.com/questions/36901/what-does-double-star-and-star-do-for-parameters) that @DYZ left above – Stephen Rauch Jan 25 '17 at 08:07
  • Thanks! But I think this would be a little deviating. Sorry didnt make it clear. My question is when to initiate instance with tuple(delhi_data and items in my example). Why namedtuple has to add a * but orderedDict does not? (City(*delhi_data) V.S. OrderedDict(items)). Thanks! – jijijude Jan 25 '17 at 08:15