将“收益"转换为Python 2.7代码声明 [英] Converting "yield from" statement to Python 2.7 code

查看:120
本文介绍了将“收益"转换为Python 2.7代码声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面在Python 3.2中有一个代码,我想在Python 2.7中运行它.我确实进行了转换(在两个版本中都放置了missing_elements的代码),但是我不确定这是否是最有效的方法.基本上,如果在missing_element函数中有两个yield from调用,例如上半部分和下半部分,该怎么办?是否将两个半部分(上半部分和下半部分)中的条目彼此追加到一个列表中,以便具有yield from调用的父递归函数将这两个半部分一起使用?

I had a code below in Python 3.2 and I wanted to run it in Python 2.7. I did convert it (have put the code of missing_elements in both versions) but I am not sure if that is the most efficient way to do it. Basically what happens if there are two yield from calls like below in upper half and lower half in missing_element function? Are the entries from the two halves (upper and lower) appended to each other in one list so that the parent recursion function with the yield from call and use both the halves together?

def missing_elements(L, start, end):  # Python 3.2
    if end - start <= 1: 
        if L[end] - L[start] > 1:
            yield from range(L[start] + 1, L[end])
        return

index = start + (end - start) // 2

# is the lower half consecutive?
consecutive_low =  L[index] == L[start] + (index - start)
if not consecutive_low:
    yield from missing_elements(L, start, index)

# is the upper part consecutive?
consecutive_high =  L[index] == L[end] - (end - index)
if not consecutive_high:
    yield from 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

    # is the lower half consecutive?
    consecutive_low =  L[index] == L[start] + (index - start)
    if not consecutive_low:
        return_list.append(missing_elements(L, start, index))

    # is the 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 you don't use the results of your yields,* you can always turn this:

yield from foo

…到这里:

for bar in foo:
    yield bar

可能会有性能上的损失,**,但是从语义上讲从来没有什么区别.

There might be a performance cost,** but there is never a semantic difference.

两个半部(上半部和下半部)中的条目是否在一个列表中彼此附加,以便父递归函数具有call的收益,并且将这两个半部一起使用?

Are the entries from the two halves (upper and lower) appended to each other in one list so that the parent recursion function with the yield from call and use both the halves together?

不!迭代器和生成器的全部要点是,您无需构建实际的列表并将它们附加在一起.

No! The whole point of iterators and generators is that you don't build actual lists and append them together.

但是效果相似:您只是从一个中屈服,然后从另一个中屈服.

But the effect is similar: you just yield from one, then yield from another.

如果您将上半部分和下半部分视为懒惰列表",那么可以,您可以将其视为懒惰附加",它会创建一个较大的懒惰列表".而且,如果您在父函数的结果上调用list,那么您当然 会得到一个实际的list,等效于将完成后得到的两个列表加在一起yield list(…)而不是yield from ….

If you think of the upper half and the lower half as "lazy lists", then yes, you can think of this as a "lazy append" that creates a larger "lazy list". And if you call list on the result of the parent function, you of course will get an actual list that's equivalent to appending together the two lists you would have gotten if you'd done yield list(…) instead of yield from ….

但是我认为反过来更容易:它的作用与for循环完全相同.

But I think it's easier to think of it the other way around: What it does is exactly the same the for loops do.

如果将两个迭代器保存到变量中,并在itertools.chain(upper, lower)上循环,那将与在第一个循环然后在第二个循环上循环相同,对吗?没什么区别.实际上,您可以将chain实施为:

If you saved the two iterators into variables, and looped over itertools.chain(upper, lower), that would be the same as looping over the first and then looping over the second, right? No difference here. In fact, you could implement chain as just:

for arg in *args:
    yield from arg


*不是生成器产生给调用者的值,而是生成器内部的yield表达式本身的值(使用send方法来自调用者),如 PEP 3156 为例.这样的代码通常取决于Python 3.3生成器的其他功能-特别是来自同一yield from的noreferrer> PEP 380 -因此必须对其进行重写.但是,如果没有,您可以使用PEP来向您显示完整的,混乱的等价物,当然您也可以减少不需要的部分.而且,如果您不使用表达式的值,它会缩减为上面的两行.


* Not the values the generator yields to its caller, the value of the yield expressions themselves, within the generator (which come from the caller using the send method), as described in PEP 342. You're not using these in your examples. And I'm willing to bet you're not in your real code. But coroutine-style code often uses the value of a yield from expression—see PEP 3156 for examples. Such code usually depends on other features of Python 3.3 generators—in particular, the new StopIteration.value from the same PEP 380 that introduced yield from—so it will have to be rewritten. But if not, you can use the PEP also shows you the complete horrid messy equivalent, and you can of course pare down the parts you don't care about. And if you don't use the value of the expression, it pares down to the two lines above.

**这不是一个很大的东西,除了使用Python 3.3或完全重组代码外,您无能为力.与将列表解析转换为Python 1.5循环完全相同,或者在X.Y版本中进行了新的优化并且您需要使用旧版本时,则为其他情况.

** Not a huge one, and there's nothing you can do about it short of using Python 3.3 or completely restructuring your code. It's exactly the same case as translating list comprehensions to Python 1.5 loops, or any other case when there's a new optimization in version X.Y and you need to use an older version.

这篇关于将“收益"转换为Python 2.7代码声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆