我正在学习 Effective Python(第 2 版)中的第 76 条,但遇到了一个我不理解的案例。具体来说,我不明白为什么要zip消耗其第一个参数的一个额外元素。考虑以下代码:
l1 = []
l2 = [1]
l1_it = iter(l1)
l2_it = iter(l2)
test_it = zip(l2_it, l1_it)
_ = list(test_it):
try:
next(l2_it)
except StopIteration:
print('This should not happen')
Run Code Online (Sandbox Code Playgroud)
这实际上打印This should not happen,我觉得这非常令人惊讶。我希望zip将其第一个参数保留在仍有一个元素要检索的状态。事实是,如果我使用zip(l1_it, l2_it)(即最短的列表在前),那么我确实可以在next(l2_it)不触发异常的情况下调用。
这是预期的吗?
zip取最短迭代的长度并限制于此。由于l1没有项目,因此l2不会处理输入的项目。
但是......使用可迭代的 Python 不知道有多少项目可用,所以它唯一的办法就是尝试获取一个项目。如果没有项目,它会得到一个例外。如果有一个项目,它现在已经从迭代器中消费了它。
也许您期待 zip_longest 的行为?https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.zip_longest
为了说明iter()行为:
>>> x = [1]
>>> x_iter = iter(x)
# We cannot get the length and unless we are prepared to fetch it,
# we cannot check if there are items available.
>>> len(x_iter)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'list_iterator' has no len()
# First item can be fetched
>>> next(x_iter)
1
# There is no second item so Python raises a StopIteration
>>> next(x_iter)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
52 次 |
| 最近记录: |