Converting "yield from" statement to Python 2.7 code -
i had code below in python 3.2 , wanted run in python 2.7. did convert (have put code of missing_elements
in both versions) not sure if efficient way it. happens if there 2 yield from
calls below in upper half , lower half in missing_element
function? entries 2 halves (upper , lower) appended each other in 1 list parent recursion function yield from
call , use both halves together?
def missing_elements(l, start, end): # python 3.2 if end - start <= 1: if l[end] - l[start] > 1: yield range(l[start] + 1, l[end]) return index = start + (end - start) // 2 # lower half consecutive? consecutive_low = l[index] == l[start] + (index - start) if not consecutive_low: yield missing_elements(l, start, index) # upper part consecutive? consecutive_high = l[index] == l[end] - (end - index) if not consecutive_high: yield missing_elements(l, index, end) def main(): l = [10, 11, 13, 14, 15, 16, 17, 18, 20] print(list(missing_elements(l, 0, len(l)-1))) l = range(10, 21) print(list(missing_elements(l, 0, len(l)-1))) def missing_elements(l, start, end): # python 2.7 return_list = [] if end - start <= 1: if l[end] - l[start] > 1: return range(l[start] + 1, l[end]) index = start + (end - start) // 2 # lower half consecutive? consecutive_low = l[index] == l[start] + (index - start) if not consecutive_low: return_list.append(missing_elements(l, start, index)) # upper part consecutive? consecutive_high = l[index] == l[end] - (end - index) if not consecutive_high: return_list.append(missing_elements(l, index, end)) return return_list
if don't use results of yields,* can always turn this:
yield foo:
… this:
for bar in foo: yield bar
there might performance cost,** there never semantic difference.
are entries 2 halves (upper , lower) appended each other in 1 list parent recursion function yield call , use both halves together?
no! whole point of iterators , generators don't build actual lists , append them together.
but effect similar: yield one, yield another.
if think of upper half , lower half "lazy lists", yes, can think of "lazy append" creates larger "lazy list". , if call list
on result of parent function, of course will actual list
that's equivalent appending 2 lists have gotten if you'd done yield list(…)
instead of yield …
.
but think it's easier think of other way around: same for
loops do.
if saved 2 iterators variables, , looped on itertools.chain(upper, lower)
, same looping on first , looping on second, right? no difference here. in fact, implement chain
just:
for arg in *args: yield arg
* not values generator yields caller, value of yield expressions themselves, within generator (which come caller using send
method), described in pep 342. you're not using these in examples. , i'm willing bet you're not in real code. coroutine-style code uses value of yield from
expression—see pep 3156 examples. such code depends on other features of python 3.3 generators—in particular, new stopiteration.value
same pep 380 introduced yield from
—so have rewritten. if not, can use pep shows complete horrid messy equivalent, , can of course pare down parts don't care about. , if don't use value of expression, pares down 2 lines above.
** not huge one, , there's nothing can short of using python 3.3 or restructuring code. it's same case translating list comprehensions python 1.5 loops, or other case when there's new optimization in version x.y , need use older version.
Comments
Post a Comment