<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sun, Jul 23, 2017 at 8:54 PM, Stephen J. Turnbull <span dir="ltr"><<a href="mailto:turnbull.stephen.fw@u.tsukuba.ac.jp" target="_blank">turnbull.stephen.fw@u.tsukuba.ac.jp</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="gmail-">C Anthony Risinger writes:<br>
<br>
 > A tuple is a tuple is a tuple. No types. Just convenient accessors.<br>
<br>
</span>That's not possible, though.  A *tuple* is an immutable collection<br>
indexed by the natural numbers, which is useful to define as a single<br>
type precisely because the natural numbers are the canonical<br>
abstraction of "sequence".  You can use the venerable idiom<br>
<br>
X = 0<br>
Y = 1<br>
<br>
point = (1.0, 1.0)<br>
x = point[X]<br>
<br>
to give the tuple "named attributes", restricting the names to Python<br>
identifiers.  Of course this lacks the "namespace" aspect of<br>
namedtuple, where ".x" has the interpretation of "[0]" only in the<br>
context of a namedtuple with an ".x" attribute.  But this is truly an<br>
untyped tuple-with-named-attributes.<br>
<br>
However, once you attach specific names to particular indexes, you<br>
have a type.  The same attribute identifiers may be reused to<br>
correspond to different indexes to represent a different "convenience<br>
type".  Since we need to be able to pass these objects to functions,<br>
pickle them, etc, that information has to be kept in the object<br>
somewhere, either directly (losing the space efficiency of tuples) or<br>
indirectly in a class-like structure.<br>
<br>
I see the convenience of the unnamed-type-typed tuple, but as that<br>
phrase suggests, I think it's fundamentally incoherent, a high price<br>
to pay for a small amount of convenience.<br>
<br>
Note that this is not an objection to a forgetful syntax that creates<br>
a namedtuple subtype but doesn't bother to record the type name<br>
explicitly in the program.  In fact, we already have that:<br>
<br>
    >>> from collections import namedtuple<br>
    >>> a = namedtuple('_', ['x', 'y'])(0,1)<br>
    >>> b = namedtuple('_', ['x', 'y'])(0,1)<br>
    >>> a == b<br>
    True<br>
    >>> c = namedtuple('_', ['a', 'b'])(0,1)<br>
<br>
This even gives you free equality as I suppose you want it:<br>
<br>
    >>> a == c<br>
    True<br>
    >>> a.x == c.a<br>
    True<br>
    >>> a.a == c.x<br>
    Traceback (most recent call last):<br>
      File "<stdin>", line 1, in <module><br>
    AttributeError: '_' object has no attribute 'a'<br>
    >>> c.x == a.a<br>
    Traceback (most recent call last):<br>
      File "<stdin>", line 1, in <module><br>
    AttributeError: '_' object has no attribute 'x'<br>
<br>
Bizarre errors are the inevitable price to pay for this kind of abuse,<br>
of course.<br>
<br>
I'm not a fan of syntaxes like "(x=0, y=1)" or "(x:0, y:1)", but I'll<br>
leave it up to others to decide how to abbreviate the abominably ugly<br>
notation I used.<br></blockquote><div><br></div>Sure sure, this all makes sense, and I agree you can't get the accessors without storing information, somewhere, that links indexes to attributes, and it makes complete sense it might be implemented as a subtype, just like namedtuple works today.<div><br></div><div>I was more commenting on what it conceptually means to have the designation "literal". It seems surprising to me that one literal has a different type from another literal with the same construction syntax. If underneath the hood it's technically a different type stored in some cached and hidden lookup table, so be it, but on the surface I think most just want a basic container with simpler named indexes.</div><div><br></div><div>Every time I've used namedtuples, I've thought it more of a chore to pick a name for it, because it's only semi-useful to me in reprs, and I simply don't care about the type, ever. I only care about the shape for comparison with other tuples. If I want typed comparisons I can always just use a class. I'd also be perfectly fine with storing the "type" as a field on the tuple itself, because it's just a value container, and that's all I'll ever want from it.</div><div><br></div><div>Alas, when I think I want a namedtuple, I usually end up using a dict subclass that assigns `self.__dict__ = self` within __new__, because this makes attribute access (and assignment) work automagically, and I care about that more than order (though it can be made to support both).</div><div><br></div><div>At the end of the day, I don't see a way to have both a literal and something that is externally "named", because the only ways to pass the name I can imagine would make it look like a value within the container itself (such as using a literal string for the first item), unless even more new syntax was added.<br></div><div><br></div><div>-- </div><div><br></div><div>C Anthony </div></div>
</div></div>