[Python-ideas] Deterministic iterator cleanup

Nathaniel Smith njs at pobox.com
Wed Oct 19 15:33:57 EDT 2016


On Wed, Oct 19, 2016 at 12:21 PM, Nathaniel Smith <njs at pobox.com> wrote:
> On Wed, Oct 19, 2016 at 11:38 AM, Paul Moore <p.f.moore at gmail.com> wrote:
>> On 19 October 2016 at 19:13, Chris Angelico <rosuav at gmail.com> wrote:
>>> Now it *won't* correctly call the end-of-iteration function, because
>>> there's no 'for' loop. This is going to either (a) require that EVERY
>>> consumer of an iterator follow this new protocol, or (b) introduce a
>>> ton of edge cases.
>>
>> Also, unless I'm misunderstanding the proposal, there's a fairly major
>> compatibility break. At present we have:
>>
>>>>> lst = [1,2,3,4]
>>>>> it = iter(lst)
>>>>> for i in it:
>> ...   if i == 2: break
>>
>>>>> for i in it:
>> ...   print(i)
>> 3
>> 4
>>>>>
>>
>> With the proposed behaviour, if I understand it, "it" would be closed
>> after the first loop, so resuming "it" for the second loop wouldn't
>> work. Am I right in that? I know there's a proposed itertools function
>> to bring back the old behaviour, but it's still a compatibility break.
>> And code like this, that partially consumes an iterator, is not
>> uncommon.
>
> Right -- did you reach the "transition plan" section? (I know it's
> wayyy down there.) The proposal is to hide this behind a __future__ at
> first + a mechanism during the transition period to catch code that
> depends on the old behavior and issue deprecation warnings. But it is
> a compatibility break, yes.

I should also say, regarding your specific example, I guess it's an
open question whether we would want list_iterator.__iterclose__ to
actually do anything. It could flip the iterator to a state where it
always raises StopIteration, or RuntimeError, or it could just be a
no-op that allows iteration to continue normally afterwards.
list_iterator doesn't have a close method right now, and it certainly
can't "close" the underlying list (whatever that would even mean), so
I don't think there's a strong expectation that it should do anything
in particular. The __iterclose__ contract is that you're not supposed
to call __next__ afterwards, so there's no real rule about what
happens if you do. And there aren't strong conventions right now about
what happens when you try to iterate an explicitly closed iterator --
files raise an error, generators just act like they were exhausted. So
there's a few options that all seem more-or-less reasonable and I
don't know that it's very important which one we pick.

-n

-- 
Nathaniel J. Smith -- https://vorpus.org


More information about the Python-ideas mailing list