Named tuples and projection

G

Giuseppe Ottaviano

I found the namedtuple very convenient for rapid prototyping code, for
functions that have to return a number of results that could grow as
the code evolves. They are more elegant than dicts, and I don't have
to create a new explicit class. Unfortunately in this situation they
lose the convenience of tuple unpacking: changing tuple's parameters
would break other functions unpacking the result.
One solution, with 3.0 syntax, would be unpacking only the used
parameters, using always a *rest
a, b, *rest = f()
so that if the tuple grows, the code keeps working.
However I find this confusing (and not avaliable in python 2.5).
I don't know if similar solutions have been proposed, I came up with
this one:

Add a method "project" that given a string of arguments (in a similar
fashion as namedtuple construction) returns a tuple with only that
items. I monkeypatched the namedtuple recipe as a proof of concept,
replace "return result" with these lines:

def _project(self, fields):
return tuple(getattr(self, field) for field in fields.split())
def _getitem(self, item):
if isinstance(item, str):
return self.project(item)
return super(result, self).__getitem__(item)

result.project = _project
result.__getitem__ = _getitem

return result

This is the result:

In [2]: X = namedtuple('X', 'a b c d')

In [3]: x = X(1, 2, 3, 4)

In [4]: a, c = x.project('a c')

In [5]: a, c
Out[5]: (1, 3)

In [6]: a, d = x['a d']

In [7]: a, d
Out[7]: (1, 4)

In [8]: x[2]
Out[8]: 3

I implemented also __getitem__ just to show another possible syntax
(maybe a bit ugly). project may be not a self-evident name, probably
something like "select" (for SQL addicts) would be more appropriate.
Other possible solutions?

Thanks,
Giuseppe
 
M

MRAB

I found the namedtuple very convenient for rapid prototyping code, for  
functions that have to return a number of results that could grow as  
the code evolves. They are more elegant than dicts, and I don't have  
to create a new explicit class. Unfortunately in this situation they  
lose the convenience of tuple unpacking: changing tuple's parameters  
would break other functions unpacking the result.
One solution, with 3.0 syntax, would be unpacking only the used  
parameters, using always a *rest
a, b, *rest = f()
so that if the tuple grows, the code keeps working.
However I find this confusing (and not avaliable in python 2.5).
I don't know if similar solutions have been proposed, I came up with  
this one:
[snip]
Provided you don't change the order of the items in the tuple, you can
just use slicing:

a, b = f()[ : 2]
 
G

Giuseppe Ottaviano

[snip]
Provided you don't change the order of the items in the tuple, you can
just use slicing:

a, b = f()[ : 2]

Yes, this is what you would normally do with tuples. But i find this
syntax very implicit and awkward. Also, you cannot skip elements, so
you often end up with things like
a, _, b = f()[:3]

The use case I posted is just the most recent that I stumbled upon.
But often a project function would have saved me a lot of typing.
Consider for example when named tuples are used for rows in an ORM (or
attributes in XML):

for person in people:
name, age, address = person['name age address']
# code
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,737
Latest member
Georgeengab

Latest Threads

Top