# Support unchecked iterables as tuple assignment sources

**URL:** <https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678>\
**Category:** Ideas\
**Created:** [February 22, 2024, 11:43pm UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678 "2024-02-22T23:43:41Z")\
**Posts on this page:** 11\
**Page:** 2

<div class="post-metadata">

**Author:** ![alicederyn](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/alicederyn/32/10282_2.png) [@alicederyn](https://discuss.python.org/u/alicederyn)\
**Post date:** [February 28, 2024, 1:17pm UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678/21 "2024-02-28T13:17:38Z")

</div>

> [@Gouvernathor](#):
>
> Now, say I want to insert a new constant for buying the treat, between the state of getting the dog and the state of giving the treat

Aha, you have a hidden extra constraint that entries must be both alphabetically ordered and monotonic. You could drop either of those. Indeed, in a lot of cases you _must_ drop one, since you are breaking backwards compatibility by renumbering.

In fact, I don’t understand why you’d want this to be an integer if you’re not serialising it. Why not just use strings? Those would be a lot more readable when debugging or logging.

---

<div class="post-metadata">

**Author:** ![chepner](https://avatars.discourse-cdn.com/v4/letter/c/22d042/32.png) [@chepner](https://discuss.python.org/u/chepner)\
**Post date:** [February 28, 2024, 3:04pm UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678/22 "2024-02-28T15:04:13Z")

</div>

> [@Gouvernathor](#):
>
> But as I said earlier, Enums are a tough thing to learn how to make work:

The solution to that problem is not to add a new feature, requiring users to know both when to use the new feature instead of `Enum` _and_ how to use `Enum` when appropriate or necessary.

---

<div class="post-metadata">

**Author:** ![Gouvernathor](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/gouvernathor/32/7957_2.png) [@Gouvernathor](https://discuss.python.org/u/Gouvernathor)\
**Post date:** [February 28, 2024, 3:22pm UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678/23 "2024-02-28T15:22:05Z")

</div>

> [@alicederyn](#):
>
> Why not just use strings?

Because they make for a lot longer code, and it’s not as easy to check they are all different as with integers. But I guess they’re an objective advantage of the Enum with its members’ `name` accessor (or is it `_name_` ? anyway).

> [@chepner](#):
>
> The solution to that problem is not to add a new feature, requiring users to know both when to use the new feature instead of `Enum`

I think that to people already preferring to use range() than enum, and as I said I encountered that code in different situations, `A, B, C, * = range()` will be far easier to learn than enum. But I hear the point that they should just learn to use enum, as I think that’s where Alice’s solution is ultimately heading to.

Also, to dig my own grave, the new syntax would introduce a dissymmetry between `*, A, B, C =`, `A, *, B, C =` and `A, B, C, * =` : the two former ones would have to exhaust the iterable whereas the latter would only consume the first three values of the iterable (potentially iterator).

---

<div class="post-metadata">

**Author:** ![PawelSwiecki](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pawelswiecki/32/108_2.png) [@PawelSwiecki](https://discuss.python.org/u/PawelSwiecki)\
**Post date:** [February 29, 2024, 1:29pm UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678/24 "2024-02-29T13:29:18Z")

</div>

I like the idea. I’d love the additional possibility of assigning the partially exhausted iterator. Using, **for illustrative purposes only** , a non-existent `(*)` syntax it would look like this:

```python
In [1]: a, b, c, (*)rest_iter = range(10)

In [2]: a, b, c, rest_iter
Out[2]: (0, 1, 2, <unpacking_iterator at 0x105896c10>)

In [3]: list(rest_iter), list(rest_iter)
Out[3]: ([3, 4, 5, 6, 7, 8, 9], [])

```

> **which would be an equivalent to**
>
> ```python
> In [1]: from itertools import islice
> 
> In [2]: range_10 = iter(range(10))
> 
> In [3]: a, b, c = islice(range_10, 3)
> 
> In [4]: a, b, c, range_10
> Out[4]: (0, 1, 2, <range_iterator at 0x103890f60>)
> 
> In [5]: list(range_10), list(range_10)
> Out[5]: ([3, 4, 5, 6, 7, 8, 9], [])
> 
> ```

The magic in the syntax alone can be a deal breaker here.

---

<div class="post-metadata">

**Author:** ![jamestwebber](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jamestwebber/32/12799_2.png) [@jamestwebber](https://discuss.python.org/u/jamestwebber)\
**Post date:** [February 29, 2024, 3:10pm UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678/25 "2024-02-29T15:10:37Z")

</div>

I was thinking this too but once I arrived at the `islice` equivalent I realized the syntax doesn’t add much.

I think the `islice` version might be more clear: the original iterator remains the same, whereas in the unpacking-magic version you create an extra redundant variable for the remainder.

An example where I might use this is the previously-mentioned scenario “grab the first few lines of a file, then read the rest”, but I don’t think

```python
header, some_extra_line, *rows = reader
for row in rows:
    ...

```

is better than

```python
header, some_extra_line = islice(reader, 2)
for row in reader: # using the same reader again
    ...

```

---

<div class="post-metadata">

**Author:** ![MFH](https://avatars.discourse-cdn.com/v4/letter/m/aeb1de/32.png) [@MFH](https://discuss.python.org/u/MFH)\
**Post date:** [March 1, 2024, 12:24pm UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678/26 "2024-03-01T12:24:45Z")

</div>

I am not sure I understand the first line of the OP,

> “It _would_ allow the syntax: `a,b,c=range(3)`.”

This **is** allowed… (I just typed it in to double-check.) So…?  
(And yes, to see only the first few terms produed by an infinite generator, which is often desired, I’d also use  
`[t for t,_ in zip(mygen(),range(20))]`. It’s short and easy to write and to read.)  
EDIT : now I found _ **“My base goal though was to remove the hardcoded `3`…”** _  
OK, then simply: `vars().update((n,v) for v,n in enumerate(["abc"]))`, or replace `"abc"` with `['first', 'second', 'third']` for longer variable names.  
It is slightly longer than the desired syntax but it is very readable, unambiguous and probably more efficient than to use more complicated structures.  
EDIT 2: to _ **“not just assign integers, but partially unpack an arbitrary iterable, e.g. lines of a file”** _  
=\> just replace `enumerate(names)` by `zip(names,iterable)`, and `(n,v) for v,n in...` isn’t needed ay more: `vars().update(zip(names, iterable))`.

---

<div class="post-metadata">

**Author:** ![chepner](https://avatars.discourse-cdn.com/v4/letter/c/22d042/32.png) [@chepner](https://discuss.python.org/u/chepner)\
**Post date:** [March 1, 2024, 2:51pm UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678/27 "2024-03-01T14:51:31Z")

</div>

> [@MFH](#):
>
> OK, then simply: `vars().update((n,v) for v,n in enumerate(["abc"]))`

You cannot rely on modifying [`vars()`](https://docs.python.org/3/library/functions.html#vars).

> Without an argument, [`vars()`](https://docs.python.org/3/library/functions.html#vars) acts like [`locals()`](https://docs.python.org/3/library/functions.html#locals). Note, the locals dictionary is only useful for reads since updates to the locals dictionary are ignored.

---

<div class="post-metadata">

**Author:** ![ntessore](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/ntessore/32/10786_2.png) [@ntessore](https://discuss.python.org/u/ntessore)\
**Post date:** [March 1, 2024, 7:48pm UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678/28 "2024-03-01T19:48:38Z")

</div>

> [@alicederyn](#):
>
> I don’t think the proposed new syntax makes it particularly clear that iteration stops at the `, *` — it looks too much like the syntax for continuing to consume values.

Thinking about this as “stop consuming the iterable” actually makes me like the proposal more. I agree on the `*` syntax, but what about a trailing `/`:

```py
# handle first two items
first, second, / = iterable
# process rest
for item in iterable:
    ...

```

---

<div class="post-metadata">

**Author:** ![chepner](https://avatars.discourse-cdn.com/v4/letter/c/22d042/32.png) [@chepner](https://discuss.python.org/u/chepner)\
**Post date:** [March 1, 2024, 10:46pm UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678/29 "2024-03-01T22:46:24Z")

</div>

> [@ntessore](#):
>
> Thinking about this as “stop consuming the iterable” actually makes me like the proposal more. I agree on the `*` syntax, but what about a trailing `/`:
> 
> ```python
> # handle first two items
> first, second, / = iterable
> 
> ```

One issue I have is that no matter what symbol you use, it will end up just whitespace away from looking like an augmented assignment operator. Not saying it’s an issue for parsing, but it’s not a great look.

```
first, second, / = iterable
first, second, /= iterable
first, second, * = iterable
first, second, *= iterable

```

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [March 1, 2024, 10:51pm UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678/30 "2024-03-01T22:51:55Z")

</div>

> [@chepner](#):
>
> One issue I have is that no matter what symbol you use, it will end up just whitespace away from looking like an augmented assignment operator. Not saying it’s an issue for parsing, but it’s not a great look.

That can be avoided with square brackets if people are bothered by it.

```python
[first, second, *] = iterable
[first, second, /] = iterable

```

---

<div class="post-metadata">

**Author:** ![jamestwebber](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jamestwebber/32/12799_2.png) [@jamestwebber](https://discuss.python.org/u/jamestwebber)\
**Post date:** [March 2, 2024, 4:03am UTC](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678/31 "2024-03-02T04:03:06Z")

</div>

I’d rather be able to slice iterators, personally (implicit `islice` using slice notation), like `iterable[:2]`.

But I know that has been proposed in the past and wasn’t particularly popular.

[Previous page](https://discuss.python.org/t/support-unchecked-iterables-as-tuple-assignment-sources/46678.md?page=1)
