[Python-ideas] Default values in multi-target assignment

Clint Hepner clint.hepner at gmail.com
Thu Apr 12 08:28:11 EDT 2018


> On 2018 Apr 12 , at 5:54 a, Serhiy Storchaka <storchaka at gmail.com> wrote:
> 
> Yet one crazy idea. What if allow default values for targets in multi-target assignment?
> 
>    >>> (a, b=0) = (1, 2)
>    >>> a, b
>    (1, 2)
>    >>> (a, b=0) = (1,)
>    >>> a, b
>    (1, 0)
>    >>> (a, b=0) = ()
>    Traceback (most recent call last):
>      File "<stdin>", line 1, in <module>
>    ValueError: not enough values to unpack (expected at least 1, got 0)
>    >>> (a, b=0) = (1, 2, 3)
>    Traceback (most recent call last):
>      File "<stdin>", line 1, in <module>
>    ValueError: too many values to unpack (expected at most 2)
> 
> Currently you need either explicitly check the length of the right-hand part (if it is a sequence and not an arbitrary iterator),
> 
>    if len(c) == 1:
>        a, = c
>        b = 0
>    elif len(c) == 2:
>        a, b = c
>    else:
>        raise TypeError
> 
> or use an intermediate function:
> 
>    def f(a, b=0):
>        return a, b
>    a, b = f(*c)
> 
> The latter can be written as an ugly one-liner:
> 
>    a, b = (lambda a, b=0: (a, b))(*c)

I think the best comparison would be

    (a, b=0, *_) = t

vs

    a, b, *_ = (*t, 0)
    (a, b, *_) = (*t, 0)

In both, I've added *_ to capture any trailing elements. It's
more necessary with the current syntax, since adding defaults
will make the tuple too long when they aren't needed.

Given that, I'm +1 on the proposal, since

 1. Defaults are more closely associated with their intended name
 2. A new tuple doesn't need to be constructed on the RH

The one minor downside, IMO, is that if you choose to omit the *_ guard,
you *must* use parentheses on the LHS, as

    a, b = 0 = t  # parsed as a, b = (0 = t)

raises a SyntaxError on the assignment to 0.

-- 
Clint



More information about the Python-ideas mailing list