mirror of
https://github.com/python/cpython.git
synced 2025-09-27 18:59:43 +00:00
[3.12] gh-113479: Link to workaround for subtle issue with takewhile() (gh-115890) (gh-115910)
This commit is contained in:
parent
f684e257b1
commit
124594913d
1 changed files with 41 additions and 33 deletions
|
@ -680,6 +680,14 @@ loops that truncate the stream.
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
Note, the element that first fails the predicate condition is
|
||||||
|
consumed from the input iterator and there is no way to access it.
|
||||||
|
This could be an issue if an application wants to further consume the
|
||||||
|
input iterator after takewhile has been run to exhaustion. To work
|
||||||
|
around this problem, consider using `more-iterools before_and_after()
|
||||||
|
<https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.before_and_after>`_
|
||||||
|
instead.
|
||||||
|
|
||||||
|
|
||||||
.. function:: tee(iterable, n=2)
|
.. function:: tee(iterable, n=2)
|
||||||
|
|
||||||
|
@ -996,32 +1004,6 @@ which incur interpreter overhead.
|
||||||
except exception:
|
except exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def before_and_after(predicate, it):
|
|
||||||
""" Variant of takewhile() that allows complete
|
|
||||||
access to the remainder of the iterator.
|
|
||||||
|
|
||||||
>>> it = iter('ABCdEfGhI')
|
|
||||||
>>> all_upper, remainder = before_and_after(str.isupper, it)
|
|
||||||
>>> ''.join(all_upper)
|
|
||||||
'ABC'
|
|
||||||
>>> ''.join(remainder) # takewhile() would lose the 'd'
|
|
||||||
'dEfGhI'
|
|
||||||
|
|
||||||
Note that the true iterator must be fully consumed
|
|
||||||
before the remainder iterator can generate valid results.
|
|
||||||
"""
|
|
||||||
it = iter(it)
|
|
||||||
transition = []
|
|
||||||
|
|
||||||
def true_iterator():
|
|
||||||
for elem in it:
|
|
||||||
if predicate(elem):
|
|
||||||
yield elem
|
|
||||||
else:
|
|
||||||
transition.append(elem)
|
|
||||||
return
|
|
||||||
|
|
||||||
return true_iterator(), chain(transition, it)
|
|
||||||
|
|
||||||
|
|
||||||
The following recipes have a more mathematical flavor:
|
The following recipes have a more mathematical flavor:
|
||||||
|
@ -1531,13 +1513,6 @@ The following recipes have a more mathematical flavor:
|
||||||
>>> list(odds)
|
>>> list(odds)
|
||||||
[1, 3, 5, 7, 9]
|
[1, 3, 5, 7, 9]
|
||||||
|
|
||||||
>>> it = iter('ABCdEfGhI')
|
|
||||||
>>> all_upper, remainder = before_and_after(str.isupper, it)
|
|
||||||
>>> ''.join(all_upper)
|
|
||||||
'ABC'
|
|
||||||
>>> ''.join(remainder)
|
|
||||||
'dEfGhI'
|
|
||||||
|
|
||||||
>>> list(subslices('ABCD'))
|
>>> list(subslices('ABCD'))
|
||||||
['A', 'AB', 'ABC', 'ABCD', 'B', 'BC', 'BCD', 'C', 'CD', 'D']
|
['A', 'AB', 'ABC', 'ABCD', 'B', 'BC', 'BCD', 'C', 'CD', 'D']
|
||||||
|
|
||||||
|
@ -1628,6 +1603,32 @@ The following recipes have a more mathematical flavor:
|
||||||
result.append(pool[-1-n])
|
result.append(pool[-1-n])
|
||||||
return tuple(result)
|
return tuple(result)
|
||||||
|
|
||||||
|
def before_and_after(predicate, it):
|
||||||
|
""" Variant of takewhile() that allows complete
|
||||||
|
access to the remainder of the iterator.
|
||||||
|
|
||||||
|
>>> it = iter('ABCdEfGhI')
|
||||||
|
>>> all_upper, remainder = before_and_after(str.isupper, it)
|
||||||
|
>>> ''.join(all_upper)
|
||||||
|
'ABC'
|
||||||
|
>>> ''.join(remainder) # takewhile() would lose the 'd'
|
||||||
|
'dEfGhI'
|
||||||
|
|
||||||
|
Note that the true iterator must be fully consumed
|
||||||
|
before the remainder iterator can generate valid results.
|
||||||
|
"""
|
||||||
|
it = iter(it)
|
||||||
|
transition = []
|
||||||
|
|
||||||
|
def true_iterator():
|
||||||
|
for elem in it:
|
||||||
|
if predicate(elem):
|
||||||
|
yield elem
|
||||||
|
else:
|
||||||
|
transition.append(elem)
|
||||||
|
return
|
||||||
|
|
||||||
|
return true_iterator(), chain(transition, it)
|
||||||
|
|
||||||
.. doctest::
|
.. doctest::
|
||||||
:hide:
|
:hide:
|
||||||
|
@ -1657,3 +1658,10 @@ The following recipes have a more mathematical flavor:
|
||||||
>>> combos = list(combinations(iterable, r))
|
>>> combos = list(combinations(iterable, r))
|
||||||
>>> all(nth_combination(iterable, r, i) == comb for i, comb in enumerate(combos))
|
>>> all(nth_combination(iterable, r, i) == comb for i, comb in enumerate(combos))
|
||||||
True
|
True
|
||||||
|
|
||||||
|
>>> it = iter('ABCdEfGhI')
|
||||||
|
>>> all_upper, remainder = before_and_after(str.isupper, it)
|
||||||
|
>>> ''.join(all_upper)
|
||||||
|
'ABC'
|
||||||
|
>>> ''.join(remainder)
|
||||||
|
'dEfGhI'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue