default value in a list

Bengt Richter bokr at oz.net
Sat Jan 22 08:32:37 EST 2005


On Fri, 21 Jan 2005 17:04:11 -0800, Jeff Shannon <jeff at ccvcorp.com> wrote:

>TB wrote:
>
>> Hi,
>> 
>> Is there an elegant way to assign to a list from a list of unknown
>> size?  For example, how could you do something like:
>> 
>> 
>>>>> a, b, c = (line.split(':'))
>> 
>> if line could have less than three fields?
>
>(Note that you're actually assigning to a group of local variables, 
>via tuple unpacking, not assigning to a list...)
>
>One could also do something like this:
>
> >>> l = "a:b:c".split(':')
> >>> a, b, c, d, e = l + ([None] * (5 - len(l)))
> >>> print (a, b, c, d, e)
>('a', 'b', 'c', None, None)
> >>>

Or
 >>> a, b, c, d, e = ('a:b:c'.split(':')+[None]*4)[:5]
 >>> print (a, b, c, d, e)
 ('a', 'b', 'c', None, None)

You could even be profligate and use *5 in place of that *4,
if that makes an easier idiom ;-)

Works if there's too many too:

 >>> a, b = ('a:b:c'.split(':')+[None]*2)[:2]
 >>> print (a, b)
 ('a', 'b')



>
>Personally, though, I can't help but think that, if you're not certain 
>how many fields are in a string, then splitting it into independent 
>variables (rather than, say, a list or dict) *cannot* be an elegant 
>solution.  If the fields deserve independent names, then they must 
>have a definite (and distinct) meaning; if they have a distinct 
>meaning (as opposed to being a series of similar items, in which case 
>you should keep them in a list), then which field is it that's 
>missing?  Are you sure it's *always* the last fields?  This feels to 
>me like the wrong solution to any problem.
>
>Hm, speaking of fields makes me think of classes.
>
> >>> class LineObj:
>...     def __init__(self, a=None, b=None, c=None, d=None, e=None):
>...         self.a = a
>...         self.b = b
>...         self.c = c
>...         self.d = d
>...         self.e = e
>...
> >>> l = "a:b:c".split(':')
> >>> o = LineObj(*l)
> >>> o.__dict__
>{'a': 'a', 'c': 'c', 'b': 'b', 'e': None, 'd': None}
> >>>
>
>This is a bit more likely to be meaningful, in that there's almost 
>certainly some logical connection between the fields of the line 
>you're splitting and keeping them as a class demonstrates that 
>connection, but it still seems a bit smelly to me.
>
That gives me an idea:

 >>> def foo(a=None, b=None, c=None, d=None, e=None, *ignore):
 ...     return a, b, c, d, e
 ...
 >>> a, b, c, d, e = foo(*'a:b:c'.split(':'))
 >>> print (a, b, c, d, e)
 ('a', 'b', 'c', None, None)

But then, might as well do:

 >>> def bar(nreq, *args):
 ...     if nreq <= len(args): return args[:nreq]
 ...     return args+ (nreq-len(args))*(None,)
 ...
 >>> a, b, c, d, e = bar(5, *'a:b:c'.split(':'))
 >>> print (a, b, c, d, e)
 ('a', 'b', 'c', None, None)
 >>> a, b = bar(2, *'a:b:c'.split(':'))
 >>> print (a, b)
 ('a', 'b')
 >>> a, b, c = bar(3, *'a:b:c'.split(':'))
 >>> print (a, b, c)
 ('a', 'b', 'c')

But usually, I would like n + tail, where I know n is a safe bet, e.g.,

 >>> def ntail(n, *args):
 ...     return args[:n]+(args[n:],)
 ...
 >>> a, b, t = ntail(2, *'a:b:c:d:e'.split(':'))
 >>> print (a, b, t)
 ('a', 'b', ('c', 'd', 'e'))
 >>> a, b, t = ntail(2, *'a:b'.split(':'))
 >>> print (a, b, t)
 ('a', 'b', ())


People have asked to be able to spell that as

     a, b, *t = 'a:b:c:d:e'.split(':')



Regards,
Bengt Richter



More information about the Python-list mailing list