python - 条件返回值——但使用 `yield from` 而不是 `return`
问题描述
在 Python 中,经常使用这种流控制编写小函数:
def get_iterstuff(source: Thingy, descr: Optional[str]) -> Iterable[Stuff]:
""" Return an iterator of Stuff instances from a given Thingy """
key = prepare_descr(descr) # may be a “str”, may be None
val = getattr(source, key, None) # val has type Optional[Iterable[Stuff]]
if not val: # None, or (in some cases) an empty
return IterStuff.EMPTY # sentinel, with the same type as val
return val # the likeliest codepath
… 一个if
语句可以提前返回——在一些这样的函数中,早于任何准备函数调用,就像这里示例的前两行中的那些。
这工作正常。return
我的意思是,我相信在具有多个语句的函数中会出现一些与窥视孔优化相关的并发症†</sup>。但总的来说,就像许多其他 Pythoneers 一样,我一直在做这种事情,以生成可测试、可维护和清晰易读的流控制函数,这些函数可以在不引起任何大的愤怒的情况下运行。
但是所以,我的问题是关于这种逻辑采用稍微不同的形式的方式,例如,当函数是使用一个或多个yield from
语句的生成器时:
def iterstuff(source: Thingy, descr: Optional[str]) -> YieldFrom[Stuff]: # ‡
key = prepare_descr(descr) # may be a “str”, may be None
val = getattr(source, key, None) # val has type Optional[Iterable[Stuff]]
if not val:
yield from tuple() # … or suchlike
else:
yield from val # the likeliest codepath
......在这个版本中,最重要的收获是:
- 第二条
yield from
语句构成函数最可能的代码路径的结尾,位于else
子句中,而不是函数代码块的顶层。 tuple(…)
构造函数对yield from
空的和可迭代的东西有这种奇怪的用法。
......现在,所以,我确实知道,由于控制失效和声明用尽后else
的事实(在其他情况下,我喜欢使用和滥用这种品质),因此必须使用 。把东西塞进去比,从第一个功能开始,为了炮制那种哨兵所需要的所有跑腿工作要容易得多。yield
yield from
tuple(…)
IterStuff.EMPTY
但是该yield from
示例确实比return
基于它的对应示例更笨拙。更脆弱。考虑较少。如果你愿意的话,代码很臭。
所以我问:yield from
构建这个版本的最清晰、最不重要、最优化的 Pythonic 方式是什么?
那个tuple()
代码疣可以吗,还是有更少的编程气味替代品?
是否存在更好的方法来进行这样的流量控制?他们中的任何一个(或我的任何例子)是否都背负着有问题的时间复杂性?
† –(即它们很难窥视孔优化;我不知道——编译器设计比我的工资等级高出很多)
‡ – “YieldFrom” 泛型类型别名简化了对这些生成器函数的注释——typing.Generator
正如所写的那样,有点过头了。它看起来像这样:
class YieldFrom(Generator[T_co, None, None]):
""" Simple “typing.Generator” alias. The generic Generator
from “typing” requires three type params:
• “yield_type” (covariant),
• “send_type” (contravariant), and
• “return_type” (covariant).
… a function containing 1..n “yield” or “yield from”
statements – without returning anything and unburdened
by any expectations of calls to its “send(…)” method
showing up in any type-festooned code – can make use
of this “YieldFrom[T]” alias. ÷Explict beats implict÷
"""
pass
解决方案
推荐阅读
- regex - 正则表达式在最后两次出现的冒号之间提取一个单词
- sorting - fhir 排序和搜索参数
- c# - 当我从控制台应用程序打开它时,为什么我的 Windows 窗体布局会发生变化?
- python - 如何仅将更新的数据从 sql server 迁移到 postgres?而不是全部数据
- java - 这个 FindBugs 空指针取消引用错误对 spring-data 规范类有效吗?
- python - ValueError:字典更新序列元素 #0 的长度为 1;2是必需的吗?
- c# - 使用 XML 并向其中添加 c# 逻辑以进行配置
- java - 用 Java 发送带有 AT 命令的 USSD
- c++ - 我可以同时为矢量和地图编写模板函数吗?
- mysql - 为什么 mySQL 结果中的 Perl Hashkey 名称不是 UTF8?