return-in-generator (B901)
源自 flake8-bugbear linter。
此规则不稳定且处于预览状态。使用需要 --preview 标志。
作用
检查同时包含 yield 或 yield from 语句的函数中是否有 return {value} 语句。
为什么这不好?
在生成器函数中使用 return {value} 在 Python 2 中是语法上无效的。在 Python 3 中,return {value} *可以*在生成器中使用;但是,yield 和 return 的组合可能会导致令人困惑的行为,因为 return 语句将导致生成器引发带有提供的值的 StopIteration,而不是将值返回给调用者。
例如,给定
from collections.abc import Iterable
from pathlib import Path
def get_file_paths(file_types: Iterable[str] | None = None) -> Iterable[Path]:
dir_path = Path(".")
if file_types is None:
return dir_path.glob("*")
for file_type in file_types:
yield from dir_path.glob(f"*.{file_type}")
读者可能会认为 get_file_paths() 将返回目录中 Path 对象的可迭代对象;但实际上,list(get_file_paths()) 的计算结果为 [],因为 return 语句导致生成器引发带有值 dir_path.glob("*") 的 StopIteration
>>> list(get_file_paths(file_types=["cfg", "toml"]))
[PosixPath('setup.cfg'), PosixPath('pyproject.toml')]
>>> list(get_file_paths())
[]
对于生成器中故意使用 return 的情况,请考虑抑制此诊断。
示例
from collections.abc import Iterable
from pathlib import Path
def get_file_paths(file_types: Iterable[str] | None = None) -> Iterable[Path]:
dir_path = Path(".")
if file_types is None:
return dir_path.glob("*")
for file_type in file_types:
yield from dir_path.glob(f"*.{file_type}")
建议改为