Filling in a tuple from unknown size list

Jon Clements joncle at googlemail.com
Fri Nov 27 11:27:41 EST 2009


On 27 Nov, 12:18, boblatest <boblat... at googlemail.com> wrote:
> Hello all,
>
> (sorry for posting from Google. I currently don't have access to my
> normal nntp account.)
>
> Here's my question: Given a list of onknown length, I'd like to be
> able to do the following:
>
> (a, b, c, d, e, f) = list
>
> If the list has fewer items than the tuple, I'd like the remaining
> tuple elements to be set to "None". If the list is longer, I'd like
> the excess elements to be ignored.
>
> The code snippet below does what I want, I was just wondering if there
> was an interesting "Pythonic" way of expressing the same thing.
>
> Thanks,
> robert
>
> def iter_inf(li, n):
>     for i in range(n):
>         if i < len(li):
>             r = li[i]
>         else:
>             r = None
>         i += 1
>         yield r
>
> li = ['a', 'b', 'c']
> (a, b, c, d, e) =  iter_inf(li, 5)
> print a, b, c, d, e

An alternative to Peter's itertools implementation is this
monstrosity...

import re

class name_elements:
    def __init__(self, iterable, *names):
        self.__names = set(names)
        if len(self.__names) != len(names):
            raise ValueError('names must be unique')
        for it, name in zip(iterable, names):
            if not re.match('[a-zA-Z][a-zA-Z0-9_]*', name):
                raise ValueError("name '%s' is not valid" % name)
            setattr(self, name, it)
    def __getattr__(self, item):
        if item not in self.__names:
            raise ValueError("name '%s' not present" % item)
        return self.__dict__.get(item, None)

>>> res = name_elements(['a', 'b', 'c'], 'a', 'b', 'c', 'd', 'e')
>>> print res.a, res.b, res.c, res.d, res.e
a b c None None
>>> print res.f
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    print res.f
  File "/home/jon/rubbish.py", line 10, in __getattr__
    raise AttributeError("name '%s' not present" % item)
AttributeError: name 'f' not present

It removes the need to know the number being unpacked (I can see this
being overlooked) and the variable names could come from a list
instead of being named in code. Asking for a name that doesn't exist
is an exception, while all other values default to None.

However, it's not totally identical to unpacking... (and most likely
slower)

I s'pose namedtuple could also be abused in a similar fashion.

Or, if you don't mind []'ing:
>>> dd = defaultdict(lambda: None)
>>> dd.update(zip(['a', 'b', 'c'], range(5)))
>>> print dd['a'], dd['c'], dd['blah']
0 2 None

Is it obvious I'm trying to avoid doing proper work!?

Cheers,
Jon.




More information about the Python-list mailing list