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 的Sequencesequence和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 :CollectionMappingIteratorSequence
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 次 |
| 最近记录: |