Che*_*evy 5 python yield generator type-hinting
返回生成器表达式的函数的正确类型注释是什么?
例如:
def foo():
return (x*x for x in range(10))
Run Code Online (Sandbox Code Playgroud)
我想不通,如果这是-> Iterator[int],-> Iterable[int],-> Generator[int, None, None],或别的东西。
如果应该有一种-最好只有一种-显而易见的方法,那么这里有什么明显的方法呢?
Wlo*_*oHu 11
快速注意:您的函数是“返回生成器的常规函数”,而不是“生成器函数”。要了解区别,请阅读此答案。
对于你来说foo,我建议使用-> Iterator[int].
这归结为你想要什么样的界面。
首先,让自己熟悉Python 文档中的这个页面,其中定义了最重要的 Python 类型的层次结构。
您可以看到这些表达式返回True:
import typing as t
issubclass(t.Iterator, t.Iterable)
issubclass(t.Generator, t.Iterator)
Run Code Online (Sandbox Code Playgroud)
您还应该注意到同一页面上有没有的Generator方法。Iterator这些方法是send、throw和close(文档),它们允许您使用生成器做更多事情,而不仅仅是简单的单次直通迭代。检查此问题以获取生成器可能性的示例:Python 生成器上“发送”函数的目的是什么?
回到选择接口。如果你希望其他人像生成器一样使用你的生成器函数的结果,即
def gen(limit: int): -> Generator[int, None, None]
for x in range(limit):
yield x
g = gen(3)
next(g) # => 0
g.send(10) # => 1
Run Code Online (Sandbox Code Playgroud)
那么你应该指定-> Generator[int, None, None].
但请注意,以上都是废话。事实上,您可以调用send,但它不会改变执行,因为gen不会对发送的值执行任何操作(没有类似的东西x = yield)。知道了这一点,您就可以限制人们使用的知识gen并将其定义为-> Iterator[int]。通过这种方式,您可以与用户签订合同“我的函数返回整数迭代器,您应该这样使用它”。如果您稍后将实现更改为,例如
def gen(limit: int): -> Iterator[int]
return iter(list(range(limit)))
Run Code Online (Sandbox Code Playgroud)
那些使用返回对象的人Generator(因为他们查看了实现)的代码将会被破坏。但是,您不应该为此烦恼,因为他们使用它的方式与您合同中指定的方式不同。因此,这种破损不是您的责任。
简而言之,如果您最终得到Generator[Something, None, None](two Nones),则考虑Iterable[Something]或Iterator[Something]。
Iteratorvs也是如此Iterable。如果您希望用户只能将您的对象与iter函数一起使用(从而在迭代上下文中使用,例如[x for x in g]),则使用Iterable. 如果您希望他们在对象上同时使用next和,请使用。iterIterator
这种思路主要适用于返回值的带注释类型。对于参数,您应该根据您想要在函数内的该对象上使用的接口(读取:方法/函数)来指定类型。
| 归档时间: |
|
| 查看次数: |
795 次 |
| 最近记录: |