[Python-ideas] Anonymous namedtuples

Joseph Martinot-Lagarde contrebasse at gmail.com
Tue Apr 19 05:49:44 EDT 2016


Hi, list !

namedtuples are really great. I would like to use them even more, for
example for functions that return multiple arguments. The problem is that
namedtuples have to be "declared" beforehand, so it would be quite tedious
to declare a nameedtuple by function, that's why I very rarely do it.

Another hting I don't like about namedtuples is the duplication of the name.
TYpical declarations look like `Point = namedtuple('Point', ['x', 'y'])`,
where `Point` is repeated two times. I'll go one step further and say that
the name is useless most of the time, so let's just get rid of it.


Proposal
========

So I thought about a new (ok, maybe it has been proposed before but I
couldn't find it) syntax for anonymous namedtuples (I put the prints as
comments, otherwise gmane is complainig about top-posting):

    my_point = (x=12, y=16)
    # (x=12, y=16)
    my_point[0]
    # 12
    my_point.y
    # 16
    type(my_point)
    # <class 'anonymousnamedtuple'>

It's just a tuple, but with names. Parenthesis would be mandatory because
`my_point = x = 12, y = 16` wouldn't work. Single elements anonymouns
namedtuples would require a trailing comma, similarely to tuples.

I'd be happy to make a factory function for my personal use, but the order
of kwargs is not respected. To have an elegant syntax, it has to be a
construct of the language.

The created objects would all be of the same class (with a better name, of
course). As it adds no keyword to the language, it would not break
compatibility.

The created objects could support some namedtuples methods: _asdict,
_replace and _fields. The two other methods _make and _source would not apply.

Performance-wise, I guess that they would be slower than tuples and
namedtuples, But to me the additionnal usability trumps the performance hit.
If you have to care about performance, you can still use a namedtuple ot
bare tuples.


Even further...
===============

This initial ideas is useful in itself, but it could be extended even
further. I've thought about a possible evolution.

The idea is that not all values has to be named: similarely to how args and
kwargs work for functions, there could be non-named values, with the same
limitations as the arguments (unnamed first, named afterwards). All values
could be retrived by indexing, and named values could also be retrieved by
their attribute name.

This way they could be used in __getitem__ as proposed in PEP 472[0], so
that __getitem__ supports additionnal keywords arguments. It would
correspond to Strategy "named tuple", with some of the cons removed:

"The namedtuple fields, and thus the type, will have to change according to
the passed arguments. This can be a performance bottleneck, and makes it
impossible to guarantee that two subsequent index accesses get the same
Index class;"

That would still be true for the performance bottleneck, but since the class
would always be the same the second problem disappears.

To minimize the performace hit, a standard tuple would be passed to
__getitiem__ if there is no keyword argument, and an anonymous namedtuple
would be passed if there is a keyword.

"the _n "magic" fields are a bit unusual, but ipython already uses them for
result history."

Those wouldn't be needed if both named and unnamed values are allowed.

"Differently from a function, the two notations gridValues[x=3, y=5, z=8]
and gridValues[3,5,8] would not gracefully match if the order is modified at
call time (e.g. we ask for gridValues[y=5, z=8, x=3]) . In a function, we
can pre-define argument names so that keyword arguments are properly
matched. Not so in __getitem__ , leaving the task for interpreting and
matching to __getitem__ itself."

Indexing already doesn't behave like a function call. Keeping the argument
order (like this proposal would imply) is a special case of not keeping it,
while the reverse is not true, so the more general solution would be
implemented.




Finally, I admit that I have no idea of how to implement this, I love python
but never looked at it's internals. Maybe my proposal is too naive, I really
hope not. 

Thanks for your attention,

Joseph




[0] https://www.python.org/dev/peps/pep-0472/



More information about the Python-ideas mailing list