Fed*_*gon 71 type-hinting python-3.x
Iterable
我不明白暗示和时的区别Sequence
。
这两者之间的主要区别是什么以及何时使用哪一个?
我认为set
是Iterable
但不是Sequence
,是否有任何内置数据类型是Sequence
但不是Iterable
?
def foo(baz: Sequence[float]):
...
# What is the difference?
def bar(baz: Iterable[float]):
...
Run Code Online (Sandbox Code Playgroud)
Zec*_* Hu 68
和抽象基类(也可以用作类型注释)大多数*遵循 Python 的Sequence
sequence和iterable定义。再具体一点:Iterable
__iter__
或 的 任何对象__getitem__
。__getitem__
是定义和的任何对象__len__
。根据定义,任何序列都是可迭代的。该类Sequence
还定义了其他方法,例如__contains__
,__reversed__
它调用两个必需的方法。一些例子:
\nlist
, tuple
,str
是最常见的序列。reversed
返回无法添加下标的reversed
对象(或list_reverseiterator
列表)。*Iterable
不完全符合 Python 的可迭代定义 \xe2\x80\x94 它只检查对象是否定义__iter__
,并且不适用于只能通过迭代的对象__getitem__
(有关详细信息,请参阅此表)。检查对象是否可迭代的黄金标准是使用iter
内置函数。
Pat*_*don 17
当编写带有参数的函数/方法时items
,我通常更Iterable
喜欢Sequence
. 下面是原因,我希望它能帮助理解其中的差异。
说的my_func_1
是:
from typing import Iterable
def my_func_1(items: Iterable[int]) -> None:
for item in items:
...
if condition:
break
return
Run Code Online (Sandbox Code Playgroud)
Iterable
为呼叫者提供最大的可能性。正确的调用包括:
my_func_1((1, 2, 3)) # tuple is Sequence, Collection, Iterator
my_func_1([1, 2, 3]) # list is MutableSequence, Sequence, Collection, Iterator
my_func_1({1, 2, 3}) # set is Collection, Iterator
my_func_1(my_dict) # dict is Mapping, Collection, Iterator
my_func_1(my_dict.keys()) # dict.keys() is MappingKeys, Set, Collection, Iterator
my_func_1(range(10)) # range is Sequence, Collection, Iterator
my_func_1(x**2 for x in range(100)) # "strict' Iterator, i.e. neither a Collection nor a Sequence
...
Run Code Online (Sandbox Code Playgroud)
...因为都是Iterable
。
给函数调用者的隐式消息是:“按原样”传输数据,只是不转换它。
如果调用者没有作为Sequence
(例如tuple
, list
) 或作为非Sequence
Collection
(例如set
) 的数据,并且因为迭代在 之前中断StopIteration
,所以如果他提供 'strict' ,它的性能也会更高Iterator
。
但是,如果函数算法(例如my_func_2
)需要多次迭代,那么Iterable
如果调用者提供“严格”,则会失败,Iterator
因为第一次迭代耗尽了它。因此使用Collection
:
from typing import Collection
def my_func_2(items: Collection[int]) -> None:
for item in items:
...
for item in items:
...
return
Run Code Online (Sandbox Code Playgroud)
如果函数算法 (my_func_3)
必须通过索引访问特定项,那么如果调用者提供 set、a或 'strict' ,则Iterable
和都会失败。因此使用 a :Collection
Mapping
Iterator
Sequence
from typing import Sequence
def my_func_3(items: Sequence[int]) -> None:
return items[5]
Run Code Online (Sandbox Code Playgroud)
结论:策略是:“使用函数可以处理的最通用的类型”。不要忘记,所有这些只是关于键入,以帮助静态类型检查器报告不正确的调用(例如,set
当Sequence
需要 a 时使用 a)。然后调用者有责任在必要时转换数据,例如:
my_func_3(tuple(x**2 for x in range(100)))
Run Code Online (Sandbox Code Playgroud)
实际上,所有这些实际上都与缩放项目长度时的性能有关。尽可能选择Iterator
。表演应作为日常任务来处理,而不是作为消防员工作组来处理。
在这个方向上,您可能会遇到这样的情况:一个函数仅处理空用例并委托其他用例,并且您不想将项转换为 aCollection
或 a Sequence
。然后做这样的事情:
from more_itertools import spy
def my_func_4(items: Iterable[int]) -> None:
(first, items) = spy(items)
if not first: # i.e. items is empty
...
else:
my_func_1(items) # Here 'items' is always a 'strict' Iterator
return
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
20412 次 |
最近记录: |