【问题标题】:python 2.7 - is there a more succint way to do this series of yield statements (in python 3, "yield from" would help)python 2.7 - 是否有更简洁的方式来执行这一系列的 yield 语句(在 python 3 中,“yield from”会有所帮助)
【发布时间】:2013-12-19 07:27:29
【问题描述】:

情况:

包含许多“yield”语句的 Python 2.7 代码。但是规格已经改变。 每个 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]

之后(如果我可以使用 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]

之后(在 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

注意:在我正在翻译的实际代码中,“产量”隐藏在各种流控制结构中。而“maybe”函数有两个参数,比较复杂。


我的问题:

观察到每次调用“maybe”都会返回 1 个值来让出,或者 0 个值来让出。 (如果有帮助,可以更改“可能”以返回值,或者在没有值时返回 None。)

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

【问题讨论】:

    标签: python-2.7 yield


    【解决方案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)
    

    但使用包装的版本来代替Nones,例如:

    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]
    

    【讨论】:

    • 谢谢 - 这正是我想要的!
    • (顺便说一句,“def maybe()”中的注释现在有点误导——不再返回列表,而是返回结果或无。)
    猜你喜欢
    • 2013-07-09
    • 2016-07-01
    • 2016-06-01
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 2013-02-09
    • 2014-05-22
    • 2020-05-09
    相关资源
    最近更新 更多