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

Stephen J. Turnbull turnbull.stephen.fw at u.tsukuba.ac.jp
Sun Jul 23 21:54:57 EDT 2017

C Anthony Risinger writes:

 > A tuple is a tuple is a tuple. No types. Just convenient accessors.

That's not possible, though.  A *tuple* is an immutable collection
indexed by the natural numbers, which is useful to define as a single
type precisely because the natural numbers are the canonical
abstraction of "sequence".  You can use the venerable idiom

X = 0
Y = 1

point = (1.0, 1.0)
x = point[X]

to give the tuple "named attributes", restricting the names to Python
identifiers.  Of course this lacks the "namespace" aspect of
namedtuple, where ".x" has the interpretation of "[0]" only in the
context of a namedtuple with an ".x" attribute.  But this is truly an
untyped tuple-with-named-attributes.

However, once you attach specific names to particular indexes, you
have a type.  The same attribute identifiers may be reused to
correspond to different indexes to represent a different "convenience
type".  Since we need to be able to pass these objects to functions,
pickle them, etc, that information has to be kept in the object
somewhere, either directly (losing the space efficiency of tuples) or
indirectly in a class-like structure.

I see the convenience of the unnamed-type-typed tuple, but as that
phrase suggests, I think it's fundamentally incoherent, a high price
to pay for a small amount of convenience.

Note that this is not an objection to a forgetful syntax that creates
a namedtuple subtype but doesn't bother to record the type name
explicitly in the program.  In fact, we already have that:

    >>> from collections import namedtuple
    >>> a = namedtuple('_', ['x', 'y'])(0,1)
    >>> b = namedtuple('_', ['x', 'y'])(0,1)
    >>> a == b
    >>> c = namedtuple('_', ['a', 'b'])(0,1)

This even gives you free equality as I suppose you want it:

    >>> a == c
    >>> a.x == c.a
    >>> a.a == c.x
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: '_' object has no attribute 'a'
    >>> c.x == a.a
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: '_' object has no attribute 'x'

Bizarre errors are the inevitable price to pay for this kind of abuse,
of course.

I'm not a fan of syntaxes like "(x=0, y=1)" or "(x:0, y:1)", but I'll
leave it up to others to decide how to abbreviate the abominably ugly
notation I used.


More information about the Python-ideas mailing list