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
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