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



我看了一位同事的代码,觉得这是对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)

我理解yieldpreprocess_docs中的使用,这样我就可以返回生成器,如果docs是一个大列表,这将很有帮助。但是我不理解standardize_text函数中yield的值。对我来说,return语句也会起到完全相同的作用。

yield有用的原因是什么?

对我来说,return语句会做完全相同的事情。

使用returnyield不同,正如ShadowRanger的评论中所解释的那样。

使用yield,调用函数会得到一个生成器对象

>>> 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'

yield有用的原因是什么?

standardize_text函数中,不,不是真的。但是preprocess_docs函数实际上使用yield返回多个值:它为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

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

相关内容

最新更新