Python 3.8:使用 if/else 条件和 return/yield 定义(总是 returns 生成器)

Python 3.8: definition with if/else condition and return/yield (always returns a generator)

[Python 3.8 | Spyder]

我试图介绍一个简单的定义,该定义将按顺序 return [1,2,3]yield 数字。

最低工作代码如下:

def example(condition):
    if condition:
        yield 1
        yield 2
        yield 3
    else:
        return [1,2,3]

如果有人尝试使用 def它将始终 return 生成器 。即使 return 在 if/else 对中最先出现:

def example(condition):
    if not condition:
        return [1,2,3]

    else:
        yield 1
        yield 2
        yield 3

似乎 python 即使 condition = False 也没有忽略收益率的存在。 这是一个意外的行为。

您可以return生成器表达式形式的生成器:

>>> def example(condition):
...     if condition:
...         return (i for i in (1, 2, 3))
...     else:
...         return [1, 2, 3]
>>> example(1)
<generator object example.<locals>.<genexpr> at 0x000000000257BBA0>

>>> example(0)
[1, 2, 3]

或者你可以单独定义生成器:

>>> def g():
...     yield 1
...     yield 2
...     yield 3
...
>>> def example(condition):
...     if condition:
...         return g()
...     else:
...         return [1, 2, 3]
>>> example(1)
<generator object g at 0x000000000257BBA0>

>>> example(0)
[1, 2, 3]

在句法上,def 语句及其组中的 yield 语句定义了一个生成器。 yield 是否在运行时实际达到是无关紧要的,事实上无法确定。

def another_example():  # this function has a well-defined type
    if random.random() < 0.5:
       yield 'What is the type of this function?'
    return 'Of course it is a generator function!'

为了使函数计算为生成器或 non-generator 值,请为生成器或 generator-expression 使用单独的定义。

def example_generator():
    yield 1
    yield 2
    yield 3

def example(condition):
    if not condition:
        return [1,2,3]
    else:
        return example_generator()

如果两条路径最终应该提供相同的值,那么在函数之外进行选择在语义上是相同的。这使得只提供一个生成器函数就足够了;结果可以在外部转换为另一种类型。

def example():
    yield 1
    yield 2
    yield 3

print("I prefer lists, such as:", list(example()))