<div dir="ltr"><span class="gmail-im" style="font-size:12.8px">> To avoid introducing a new built-in, we could do object.bag = SimpleNamespace<br><br></span><span style="font-size:12.8px">I am liking the idea of making SimpleNamespace more accessible, but maybe we need to think a bit more about why one </span><span style="font-size:12.8px">might want a tuple-with-names, rather than just an easy way to create</span><br style="font-size:12.8px"><span style="font-size:12.8px">an object-with-just-attributes.</span><br style="font-size:12.8px"><br style="font-size:12.8px"><span style="font-size:12.8px">That is -- how many times do folks use a namedtuple rather than</span><br style="font-size:12.8px"><span style="font-size:12.8px">SimpleNamespace just because they know about it, rather than because</span><br style="font-size:12.8px"><span style="font-size:12.8px">they really need it. I know that is often the case...</span><br style="font-size:12.8px"><br>but here are some reasons to want an actual tuple (or, an actual ImutableSequence)<br><br style="font-size:12.8px"><span style="font-size:12.8px">1) Backward compatibility with tuples.</span><br style="font-size:12.8px"><span style="font-size:12.8px"> This may have been a common use case when they were new, and maybe</span><br style="font-size:12.8px"><span style="font-size:12.8px">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.</span><br style="font-size:12.8px"><br><div><span style="font-size:12.8px">2) order-preserving: this makes them a good match for "records" from a</span><br style="font-size:12.8px"><span style="font-size:12.8px">DB or CSV file or something.</span><br style="font-size:12.8px"><br>3) unpacking: x, y = a_point<br><br></div><div>4) iterating: for coord in a_point:<div> ...</div><br style="font-size:12.8px"><span style="font-size:12.8px">5) immutability: being able to use them as a key in a dict.</span><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">What else?</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">So the question is -- If we want an easier way to create a namedtuple-like object -- which of these features are desired?</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">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.</span></div><div><br></div><div><span style="font-size:12.8px">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.</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">And will people really get confused if:</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><font face="monospace, monospace">ntuple(x=1, y=2) == ntuple(y=2, x=1)</font></span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">returns False?</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">If so -- then, if we are will to introduce new syntax, then we can make that more clear.</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">Note that: </span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><font face="monospace, monospace">ntuple(x=1, y=2) == ntuple(z=1, w=2)</font></span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">Should also be False.</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">and </span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-family:monospace,monospace;font-size:12.8px">ntuple(x=1, y=2) == (1, 2)</span><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">also False (this is losing tuple-compatibility)</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">That is, the names, and the values, and the order are all fixed.</span></div><div><br></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">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.</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">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.</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">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.</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">Have I got that right?</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">Of course, this will make it hard to back-port a "ntuple" implementation....</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">And</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><font face="monospace, monospace">ntuple(('x', 2), ('y', 3))</font></span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">is unfortunate.</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">-CHB</span></div><div><br></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><br></span><div class="gmail-yj6qo gmail-ajU" style="font-size:12.8px"></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><br></span></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jul 27, 2017 at 4:48 AM, Nick Coghlan <span dir="ltr"><<a href="mailto:ncoghlan@gmail.com" target="_blank">ncoghlan@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 27 July 2017 at 10:38, Steven D'Aprano <<a href="mailto:steve@pearwood.info">steve@pearwood.info</a>> wrote:<br>
> On Thu, Jul 27, 2017 at 11:46:45AM +1200, Greg Ewing wrote:<br>
>> Nick Coghlan wrote:<br>
>> >The same applies to the ntuple concept, expect there it's the fact<br>
>> >that it's a *tuple* that conveys the "order matters" expectation.<br>
>><br>
>> That assumes there's a requirement that it be a tuple in<br>
>> the first place. I don't see that requirement in the use<br>
>> cases suggested here so far.<br>
><br>
> This is an excellent point. Perhaps we should just find a shorter name<br>
> for SimpleNamespace and promote it as the solution.<br>
><br>
> I'm not sure about other versions, but in Python 3.5 it will even save<br>
> memory for small records:<br>
><br>
> py> from types import SimpleNamespace<br>
> py> spam = SimpleNamespace(flavour='up', charge='1/3')<br>
> py> sys.getsizeof(spam)<br>
> 24<br>
<br>
</span>sys.getsizeof() isn't recursive, so this is only measuring the<br>
overhead of CPython's per-object bookkeeping. The actual storage<br>
expense is incurred via the instance dict:<br>
<br>
>>> sys.getsizeof(spam.__dict__)<br>
240<br>
>>> data = dict(charge='1/3', flavour='up')<br>
>>> sys.getsizeof(data)<br>
240<br>
<br>
Note: this is a 64-bit system, so the per-instance overhead is also<br>
higher (48 bytes rather than 24), and tuple incur a cost of 8 bytes<br>
per item rather than 4 bytes.<br>
<br>
It's simply not desirable to rely on dicts for this kind of use case,<br>
as the per-instance cost of their bookkeeping machinery is overly high<br>
for small data classes and key-sharing only mitigates that problem, it<br>
doesn't eliminate it.<br>
<br>
By contrast, tuples are not only the most memory efficient data<br>
structure Python offers, they're also one of the fastest to allocate:<br>
since they're fixed length, they can be allocated as a single<br>
contiguous block, rather than requiring multiple memory allocations<br>
per instance (and that's before taking the free list into account).<br>
<br>
As a result, "Why insist on a tuple?" has three main answers:<br>
<br>
- lowest feasible per-instance memory overhead<br>
- lowest feasible runtime allocation cost overhead<br>
- backwards compatibility with APIs that currently return a tuple<br>
without impacting either of the above benefits<br>
<span class="im HOEnZb"><br>
Cheers,<br>
Nick.<br>
<br>
--<br>
Nick Coghlan | <a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a> | Brisbane, Australia<br>
</span><div class="HOEnZb"><div class="h5">______________________________<wbr>_________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/<wbr>mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/<wbr>codeofconduct/</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><br>Christopher Barker, Ph.D.<br>Oceanographer<br><br>Emergency Response Division<br>NOAA/NOS/OR&R (206) 526-6959 voice<br>7600 Sand Point Way NE (206) 526-6329 fax<br>Seattle, WA 98115 (206) 526-6317 main reception<br><br><a href="mailto:Chris.Barker@noaa.gov" target="_blank">Chris.Barker@noaa.gov</a></div>
</div>