python 2.7 - 是否有更简洁的方法来完成这一系列的yield语句(在python 3中,“yield from”会有所帮助)

时间:2013-12-19 07:27:29

标签: python-2.7 yield

情况:

Python 2.7代码,包含许多“yield”语句。但规格已发生变化。 每个yield都会调用一个用于始终返回值的函数。现在结果有时是应该产生的值,但有时候不应该产生任何价值。

哑巴示例:

在:

def always(x):
    return 11 * x

def do_stuff():
    # ... other code; each yield is buried inside an if or other flow construct ...
    # ...
    yield always(1)
    # ...
    yield always(6)
    # ...
    yield always(5)

print( list( do_stuff() ) )

=>

[11, 66, 55]

AFTER(如果我可以使用Python 3,但目前不是一个选项):

def maybe(x):
    """ only keep odd value; returns list with 0 or 1 elements. """
    result = 11 * x
    return [result] if bool(result & 1) else []

def do_stuff():
    # ...
    yield from maybe(1)
    # ...
    yield from maybe(6)
    # ...
    yield from maybe(5)

=>

[11, 55]

AFTER(在Python 2.7中):

def maybe(x):
    """ only keep odd value; returns list with 0 or 1 elements. """
    result = 11 * x
    return [result] if bool(result & 1) else []

def do_stuff():
    # ...
    for x in maybe(1): yield x
    # ...
    for x in maybe(6): yield x
    # ...
    for x in maybe(5): yield x

注意:在我翻译的实际代码中,“yield”被隐藏在各种流控制结构中。而“可能”功能有两个参数,而且更复杂。


我的问题:

注意每次调用“maybe”都会返回1个值来生成,或者返回0个值。 (更改“可能”以返回值,或者在没有值的情况下返回“无”,如果有帮助,则可以。)

鉴于这种0/1的情况,还有更简洁的代码方式吗?

1 个答案:

答案 0 :(得分:1)

如果你说你可以退回None,那么我会把代码保留在原来的位置:

def maybe(x):
    """ only keep odd value; returns either element or None """
    result = 11 * x
    if result & 1: return result

def do_stuff():
    yield maybe(1)
    yield maybe(6)
    yield maybe(5)

但使用包装版本而不是None s,如:

def do_stuff_use():
    return (x for x in do_stuff() if x is not None)

如果你愿意的话,你甚至可以将整件事装在装饰师中:

import functools

def yield_not_None(f):
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        return (x for x in f(*args, **kwargs) if x is not None)
    return wrapper

@yield_not_None
def do_stuff():
    yield maybe(1)
    yield maybe(6)
    yield maybe(5)

之后

>>> list(do_stuff())
[11, 55]