[Python-ideas] namedtuple literals [Was: RE a new namedtuple]

Chris Barker chris.barker at noaa.gov
Thu Jul 27 12:22:05 EDT 2017

> To avoid introducing a new built-in, we could do object.bag =

I am liking the idea of making SimpleNamespace more accessible, but maybe
we need to think a bit more about why one might want a tuple-with-names,
rather than just an easy way to create
an object-with-just-attributes.

That is -- how many times do folks use a namedtuple rather than
SimpleNamespace just because they know about it, rather than because
they really need it. I know that is often the case...

but here are some reasons to want an actual tuple (or, an actual

1) Backward compatibility with tuples.
    This may have been a common use case when they were new, and maybe
still is, but If we are future-looking, I don't think this the the primary
use case. But maybe some of the features you get from that are important.

2) order-preserving: this makes them a good match for "records" from a
DB or CSV file or something.

3) unpacking: x, y = a_point

4) iterating: for coord in a_point:

5) immutability: being able to use them as a key in a dict.

What else?

So the question is -- If we want an easier way to create a namedtuple-like
object -- which of these features are desired?

Personally, I think an immutable SimpleNamespace would be good. And if you
want the other stuff, use a NamedTuple. And a quick and easy way to make
one would be nice.

I understand that the ordering could be confusing to folks, but I'm still
thinking yes -- in the spirit of duck-typing, I think having to think
about the Type is unfortunate.

And will people really get confused if:

ntuple(x=1, y=2) == ntuple(y=2, x=1)

returns False?

If so -- then, if we are will to introduce new syntax, then we can make
that more clear.

Note that:

ntuple(x=1, y=2) == ntuple(z=1, w=2)

Should also be False.


ntuple(x=1, y=2) == (1, 2)

also False (this is losing tuple-compatibility)

That is, the names, and the values, and the order are all fixed.

If we use a tuple to define the "type" == ('x','y') then it's easy enough
to cache and compare based on that. If, indeed, you need to cache at all.

BTW, I think we need to be careful about what assumptions we are making in
terms of "dicts are order-preserving". My understanding is that the fact
that the latest dict in cpython is order preserving should be considered an
implementation detail, and not relied on.

But that we CAN count on **kwargs being order-preserving. That is, **kwargs
is an order-preserving mapping, but the fact that it IS a dict is an
implementation detail.

Have I got that right?

Of course, this will make it hard to back-port a "ntuple" implementation....


ntuple(('x', 2), ('y', 3))

is unfortunate.


On Thu, Jul 27, 2017 at 4:48 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:

> On 27 July 2017 at 10:38, Steven D'Aprano <steve at pearwood.info> wrote:
> > On Thu, Jul 27, 2017 at 11:46:45AM +1200, Greg Ewing wrote:
> >> Nick Coghlan wrote:
> >> >The same applies to the ntuple concept, expect there it's the fact
> >> >that it's a *tuple* that conveys the "order matters" expectation.
> >>
> >> That assumes there's a requirement that it be a tuple in
> >> the first place. I don't see that requirement in the use
> >> cases suggested here so far.
> >
> > This is an excellent point. Perhaps we should just find a shorter name
> > for SimpleNamespace and promote it as the solution.
> >
> > I'm not sure about other versions, but in Python 3.5 it will even save
> > memory for small records:
> >
> > py> from types import SimpleNamespace
> > py> spam = SimpleNamespace(flavour='up', charge='1/3')
> > py> sys.getsizeof(spam)
> > 24
> sys.getsizeof() isn't recursive, so this is only measuring the
> overhead of CPython's per-object bookkeeping. The actual storage
> expense is incurred via the instance dict:
>     >>> sys.getsizeof(spam.__dict__)
>     240
>     >>> data = dict(charge='1/3', flavour='up')
>     >>> sys.getsizeof(data)
>     240
> Note: this is a 64-bit system, so the per-instance overhead is also
> higher (48 bytes rather than 24), and tuple incur a cost of 8 bytes
> per item rather than 4 bytes.
> It's simply not desirable to rely on dicts for this kind of use case,
> as the per-instance cost of their bookkeeping machinery is overly high
> for small data classes and key-sharing only mitigates that problem, it
> doesn't eliminate it.
> By contrast, tuples are not only the most memory efficient data
> structure Python offers, they're also one of the fastest to allocate:
> since they're fixed length, they can be allocated as a single
> contiguous block, rather than requiring multiple memory allocations
> per instance (and that's before taking the free list into account).
> As a result, "Why insist on a tuple?" has three main answers:
> - lowest feasible per-instance memory overhead
> - lowest feasible runtime allocation cost overhead
> - backwards compatibility with APIs that currently return a tuple
> without impacting either of the above benefits
> Cheers,
> Nick.
> --
> Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/


Christopher Barker, Ph.D.

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris.Barker at noaa.gov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20170727/f102c078/attachment.html>

More information about the Python-ideas mailing list