这是对 yield 语句的错误使用吗?

Is this a bad use of a `yield` statement?

我正在查看一位同事的代码,我觉得这是对 yield 语句的不必要使用。事情是这样的:

def standardize_text(text: str):
    pattern = r"ABC" # some regex
    yield re.sub(pattern, "X", text)

def preprocess_docs(docs: List[str]):
    for doc in docs:
        yield standardize_text(doc)

我了解 preprocess_docsyield 的用法,因此我可以 return 一个生成器,如果 docs 是一个大列表,这将很有帮助。但是我不明白 standardize_text 函数中 yield 的值。对我来说,return 语句会做同样的事情。

为什么 yield 会有用?

To me, a return statement would do the exact same thing.

使用 returnyield 不同,如 .

中所述

使用 yield,调用函数会得到 generator object:

>>> standardize_text("ABCD")
<generator object standardize_text at 0x10561f740>

生成器可以产生多个结果(与使用 return 的函数不同)。这个生成器 碰巧 只生成一个项目,它是一个字符串(re.sub 的结果)。例如,您可以将生成器的结果收集到 list() 中,或者只使用 next():

获取第一个结果
>>> list(standardize_text("ABCD"))
['XD']

>>> g = standardize_text("ABCD")
>>> next(g)
'XD'
>>> next(g) # raises StopIteration, indicating the generator has finished

如果我们将函数更改为使用 return:

def standardize_text(text: str):
    pattern = r"ABC" # some regex
    return re.sub(pattern, "X", text)

然后调用该函数只会给我们 单一结果 — 不需要 list()next()

>>> standardize_text("ABCD")
'XD'

Is there a reason why that yield would be useful?

standardize_text 函数中,不,不是真的。但是您的 preprocess_docs 函数实际上确实利用 yield 返回多个值:它 returns 一个生成器,对于 docs 中的每个值都有一个结果。这些结果要么是生成器本身(在您的原始代码中使用 yield),要么是字符串(如果我们将 standardize_text 更改为使用 return)。

def preprocess_docs(docs: List[str]):
    for doc in docs:
        yield standardize_text(doc)

# returns a generator because the implementation uses "yield"
>>> preprocess_docs(["ABCD", "AAABC"])
<generator object preprocess_docs at 0x10561f820>

# with standardize_text using "yield re.sub..."
>>> for x in preprocess_docs(["ABCD", "AAABC"]): print(x)
... 
<generator object standardize_text at 0x1056cce40>
<generator object standardize_text at 0x1056cceb0>


# with standardize_text using "return re.sub..."
>>> for x in preprocess_docs(["ABCD", "AAABC"]): print(x)
... 
XD
AAX

注意:在 Python 3 的 async/await 之前,一些并发库使用 yield 的方式与现在使用 await 的方式相同。例如,Twisted's @inlineCallbacks。我认为这与您的问题没有直接关系,但为了完整起见,我将其包括在内。