英文:
How to type annotate a chunker function?
问题
以下是您要翻译的代码部分:
from typing import Iterator, List, Any, TypeVar
T = TypeVar('T')
def chunker(seq: Iterator[T], size: int) -> Iterator[List[T]]:
for i in seq:
yield []
for i in chunker([1, 2, 3, 4], 5):
pass
请注意,代码部分已经被翻译成中文。如果您需要进一步的帮助,请随时提问。
英文:
I try the following:
from typing import Iterator, List, Any, TypeVar
T = TypeVar('T')
def chunker(seq: Iterator[T], size: int) -> Iterator[List[T]]:
for i in seq:
yield []
for i in chunker([1, 2, 3, 4], 5):
pass
However, pyright tells me that:
test.py:5:18 - error: Argument of type "list[int]" cannot be assigned to parameter "seq" of type "Iterator[T@chunker]" in function "chunker"
  "list[int]" is incompatible with protocol "Iterator[T@chunker]"
    "__next__" is not present (reportGeneralTypeIssues)
1 error, 0 warnings, 0 informations
How should I annotate a function that takes something that you can for i in seq
it?
I tried searching on stack and google, but I guess like my google-fu is not good enough. I could use Union[Iterator[T], List[T]]
but I think there should be something better?
答案1
得分: 2
以下是翻译好的部分:
迭代器是具有状态的对象,它在迭代过程中记住了自己的位置。它具有一个 __next__
方法,该方法返回迭代中的下一个值,更新状态以指向下一个值,并通过引发 StopIteration
信号来表示完成。
正如您所见,列表没有 __next__
方法:
>>> [1,2,3].__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__next__'
相反,您真正想要的是一个可迭代对象。可迭代对象包括:
- 任何可以进行循环遍历的东西(例如,您可以循环遍历字符串或文件)
- 可以出现在 for 循环右侧的任何东西:
for x in iterable: ...
- 您可以使用
iter()
调用的任何东西,它将返回一个迭代器:iter(obj)
- 定义了返回新迭代器的
__iter__
的对象
列表确实是一个可迭代对象:
>>> [1,2,3].__iter__()
<list_iterator object at 0x103e68310>
更多信息可以在此问题中找到:https://stackoverflow.com/q/9884132/5296106
因此,您应该将示例重写为:
from collections.abc import Generator, Iterable
from typing import Any, TypeVar
T = TypeVar('T')
def chunker(seq: Iterable[T], size: int) -> Generator[list[T], None, None]:
for i in seq:
yield []
for i in chunker([1, 2, 3, 4], 5):
pass
请注意,自Python版本3.9起,typing.Iterable
已弃用。更多详细信息可在此处找到。另外,typing.List
是 list
的已弃用别名(更多详细信息请见此处)。
更简单的方法是使用 Iterator
而不是 Generator
(每个生成器都是迭代器!!):
from collections.abc import Iterable, Iterator
from typing import Any, TypeVar
T = TypeVar('T')
def chunker(seq: Iterable[T], size: int) -> Iterator[list[T]]:
for i in seq:
yield []
for i in chunker([1, 2, 3, 4], 5):
pass
英文:
An iterator is an object with state that remembers where it is during iteration. It has a __next__
method that returns the next value in the iteration, updates the state to point at the next value and signals when it is done by raising StopIteration
.
As you can see, a list does not have a __next__
method:
>>> [1,2,3].__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__next__'
Instead, what you really want here is an iterable. An iterable is:
- anything that can be looped over (i.e. you can loop over a string or file)
- anything that can appear on the right-side of a for-loop:
for x in iterable: ...
- anything you can call with
iter()
that will return an iterator:iter(obj)
- an object that defines
__iter__
that returns a fresh iterator
A list is indeed an iterable:
>>> [1,2,3].__iter__()
<list_iterator object at 0x103e68310>
More info can be found in this question: https://stackoverflow.com/q/9884132/5296106
So you should rewrite your example as:
from collections.abc import Generator, Iterable
from typing import Any, TypeVar
T = TypeVar('T')
def chunker(seq: Iterable[T], size: int) -> Generator[list[T], None, None]:
for i in seq:
yield []
for i in chunker([1, 2, 3, 4], 5):
pass
Notice that since Python version 3.9, typing.Iterable
is deprecated. More details can be found here. Also, typing.List
is a deprecated alias of list
(more details here).
A simpler way is to use Iterator
instead of Generator
(every generator is an iterator!!):
from collections.abc import Iterable, Iterator
from typing import Any, TypeVar
T = TypeVar('T')
def chunker(seq: Iterable[T], size: int) -> Iterator[list[T]]:
for i in seq:
yield []
for i in chunker([1, 2, 3, 4], 5):
pass
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论