为了账号安全,请及时绑定邮箱和手机立即绑定

将“ yield from”语句转换为Python 2.7代码

将“ yield from”语句转换为Python 2.7代码

繁星coding 2019-11-30 15:08:45
我在下面的Python 3.2中有一个代码,我想在Python 2.7中运行它。我确实进行了转换(已经missing_elements在两个版本中都放了代码),但是我不确定这是否是最有效的方法。基本上,如果函数的yield from上半部和下半部有两个类似下面的调用,会发生什么情况missing_element?是否将两个半部分(上半部分和下半部分)中的条目彼此追加到一个列表中,以便父递归函数与yield from调用一起使用并将这两个半部分一起使用?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])        returnindex = 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
查看完整描述

3 回答

?
蓝山帝景

TA贡献1843条经验 获得超7个赞

如果您不使用收益率*,则可以随时将其转换为:


yield from foo

…变成这样:


for bar in foo:

    yield bar

可能会有性能成本**,但从语义上讲永远不会有差异。


是否将两个半部分(上半部分和下半部分)中的条目彼此追加到一个列表中,以使父递归函数与call的收益并同时使用这两个半部分?


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


但是效果是相似的:您只是从一种收益,然后从另一种收益。


如果您将上半部分和下半部分视为“懒惰列表”,则可以,您可以将其视为“懒惰附加”,它会创建一个较大的“懒惰列表”。而且,如果您调用list父函数的结果,那么您当然会得到一个实际值list,该值等于将如果执行yield list(…)而不是所获得的两个列表加在一起yield from …。


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


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


for arg in *args:

    yield from arg

*不是生成器产生给调用者的值,而是生成器内部的yield表达式本身的值(使用send方法从调用者产生),如PEP 342中所述。您没有在示例中使用这些。而且我敢打赌您不在您的真实代码中。但是协程式代码通常使用yield from表达式的值- 有关示例,请参阅PEP 3156。此类代码通常取决于Python 3.3生成器的其他功能-特别是StopIteration.value来自引入了同一PEP 380的新功能yield from-因此必须将其重写。但是,如果没有,您可以使用PEP来向您显示完整的,混乱的等价物,当然您也可以减少不需要的部分。而且,如果您不使用表达式的值,它将缩减为上面的两行。


**数量不多,除了使用Python 3.3或完全重组代码外,您无能为力。这与将列表解析转换为Python 1.5循环完全相同,或者在XY版本中进行了新的优化并且您需要使用旧版本时,则与其他情况完全相同。


查看完整回答
反对 回复 2019-11-30
?
繁星淼淼

TA贡献1775条经验 获得超11个赞

我只是碰到这个问题,我使用的是一个有点困难,因为我需要返回值的yield from:


result = yield from other_gen()

不能将其表示为简单的for循环,但可以用以下方式重现:


_iter = iter(other_gen())

try:

    while True: #broken by StopIteration

        yield next(_iter)

except StopIteration as e:

    if e.args:

        result = e.args[0]

    else:

        result = None

希望这将帮助遇到相同问题的人们。:)


查看完整回答
反对 回复 2019-11-30
?
慕田峪9158850

TA贡献1794条经验 获得超7个赞

用for循环替换它们:


yield from range(L[start] + 1, L[end])


==>


for i in range(L[start] + 1, L[end]):

    yield i

关于元素也是如此:


yield from missing_elements(L, index, end)


==>


for el in missing_elements(L, index, end):


查看完整回答
反对 回复 2019-11-30
  • 3 回答
  • 0 关注
  • 752 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信