使用枚举的 for 循环意外终止
for loop using enumerate terminates unexpectedly
这是一个遍历枚举对象的简单 for 循环。由于(我在评论中提到的这一行)而终止。这是为什么?
enum_arr = enumerate(arr)
for ele in enum_arr:
print(ele)
print(list(enum_arr)[ele[0]:]) # terminates due to this line
输出:
(0, 0)
[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
如果我注释掉第二个打印语句,那么:
输出:
(0, 0)
(1, 1)
(2, 2)
(3, 3)
(4, 4)
(5, 5)
不出所料。
为什么会这样?
enumerate()
给你一个 iterator object。迭代器就像书中的书签,只能向前移动;一旦读到书的末尾就不能再返回了,必须创建一个新书签。
然后您在两个地方使用该迭代器; for
循环和 list()
。 list()
函数将书签一直移动到末尾,因此 for
循环无法再将其移动。
如果你想使用一个单独的、独立的迭代器,你必须在循环中创建一个 new enumerate()
对象:
enum_arr = enumerate(arr)
for ele in enum_arr:
print(ele)
print(list(enumerate(arr[ele[0]:], ele[0])))
这确实需要 arr
本身 而不是 迭代器,它必须是一个序列,以便您可以对其进行索引。我在这里假设您有一个列表、元组、范围或类似的值。
请注意,我传入了两次 ele[0]
,enumerate()
的第二个参数允许您设置计数器的起始值。
这里使用元组赋值来分离计数和值更容易:
for count, value in enum_arr:
print((count, value))
print(list(enumerate(arr[count:], count)))
演示:
>>> arr = range(6)
>>> enum_arr = enumerate(arr)
>>> for count, value in enum_arr:
... print((count, value))
... print(list(enumerate(arr[count:], count)))
...
(0, 0)
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
(1, 1)
[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
(2, 2)
[(2, 2), (3, 3), (4, 4), (5, 5)]
(3, 3)
[(3, 3), (4, 4), (5, 5)]
(4, 4)
[(4, 4), (5, 5)]
(5, 5)
[(5, 5)]
回到书的类比,要求arr
是一个序列:只要arr
是有页码的书,您可以随时添加更多书签。如果它是其他一些 iterable type,那么您无法对其进行索引,因此必须找到一些其他方法来 'skip ahead' 并再次返回。进一步延伸类比:假设这本书正在 流式传输 给你,一次一页,那么一旦你收到所有页面就不能返回。解决方案可能是首先创建页面的本地缓存;如果你可以节省 cached_copy = list(arr)
可以完成的内存。请注意,您必须确保您收到的书的长度不会超过您实际拥有的 space。有些迭代器是无限的,所以需要无限的内存!
这是一个遍历枚举对象的简单 for 循环。由于(我在评论中提到的这一行)而终止。这是为什么?
enum_arr = enumerate(arr)
for ele in enum_arr:
print(ele)
print(list(enum_arr)[ele[0]:]) # terminates due to this line
输出:
(0, 0)
[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
如果我注释掉第二个打印语句,那么:
输出:
(0, 0)
(1, 1)
(2, 2)
(3, 3)
(4, 4)
(5, 5)
不出所料。 为什么会这样?
enumerate()
给你一个 iterator object。迭代器就像书中的书签,只能向前移动;一旦读到书的末尾就不能再返回了,必须创建一个新书签。
然后您在两个地方使用该迭代器; for
循环和 list()
。 list()
函数将书签一直移动到末尾,因此 for
循环无法再将其移动。
如果你想使用一个单独的、独立的迭代器,你必须在循环中创建一个 new enumerate()
对象:
enum_arr = enumerate(arr)
for ele in enum_arr:
print(ele)
print(list(enumerate(arr[ele[0]:], ele[0])))
这确实需要 arr
本身 而不是 迭代器,它必须是一个序列,以便您可以对其进行索引。我在这里假设您有一个列表、元组、范围或类似的值。
请注意,我传入了两次 ele[0]
,enumerate()
的第二个参数允许您设置计数器的起始值。
这里使用元组赋值来分离计数和值更容易:
for count, value in enum_arr:
print((count, value))
print(list(enumerate(arr[count:], count)))
演示:
>>> arr = range(6)
>>> enum_arr = enumerate(arr)
>>> for count, value in enum_arr:
... print((count, value))
... print(list(enumerate(arr[count:], count)))
...
(0, 0)
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
(1, 1)
[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
(2, 2)
[(2, 2), (3, 3), (4, 4), (5, 5)]
(3, 3)
[(3, 3), (4, 4), (5, 5)]
(4, 4)
[(4, 4), (5, 5)]
(5, 5)
[(5, 5)]
回到书的类比,要求arr
是一个序列:只要arr
是有页码的书,您可以随时添加更多书签。如果它是其他一些 iterable type,那么您无法对其进行索引,因此必须找到一些其他方法来 'skip ahead' 并再次返回。进一步延伸类比:假设这本书正在 流式传输 给你,一次一页,那么一旦你收到所有页面就不能返回。解决方案可能是首先创建页面的本地缓存;如果你可以节省 cached_copy = list(arr)
可以完成的内存。请注意,您必须确保您收到的书的长度不会超过您实际拥有的 space。有些迭代器是无限的,所以需要无限的内存!