Python中range和len与enumerate的区别

7
我从 range(len(list)) 或 enumerate(list)? 中了解到,使用 range(len(s)) 不是编写 Python 的很好的方式。如果我们不需要循环 len(s) 次,而是需要循环例如 len(s)//3 次或 len(s)-5 次等,有什么替代的方法可以编写 for 循环呢?是否可以将这些循环转换为使用 enumerate 呢?
例如,我有一个项目,其中我有一个由 3n 个元素 's [0],s [1],...,s [3n-1]' 组成的列表,并且我需要以 nx3 表格形式打印它们。我编写的代码类似于:
for i in range(len(s)//3):
    row = str(s[3*i]) + " " + str(s[3*i+1]) + " " + str(s[3*i+2])
    print(row)

3
你能否给出一个更具体的例子,说明你想做什么? - Chris_Rands
1
可能是Only index needed: enumerate or (x)range?的重复问题。 - Abdulrahman Bres
这并不完全是一个重复的问题,因为这个问题还询问了如何迭代列表的一部分。 - Adam Barnes
1
使用 range(len(s)) 不是编写 Python 的很好的方式,不确定您是从哪里得到这个想法的,是从那个问题还是其他地方。在 Python 中完全可以使用它。不建议的是在循环中迭代索引,然后获取元素;此时最好使用 enumerate - jdehesa
@jdehesa 我从 https://python-forum.io/Thread-Basic-Never-use-for-i-in-range-len-sequence 阅读了这篇文章。 - Jaakko Seppälä
2
@user2219896 是的,重点是当你想要迭代列表的元素时,通常不要使用 range(len(l))(尽管仍然可能有一些情况下它是有意义的)。但是如果你只想迭代一系列数字,无论是到达 len(l) 还是任何其他数字,这是正确的方法(实际上,这正是 range/xrange 的目的)。在我看来,在这种情况下使用 enumerate 并忽略列表元素是不必要的,最重要的是,它稍微不够明确,因为你 没有 使用列表元素。 - jdehesa
4个回答

14

如果您正在遍历整个列表:

for x in lst:
    print(x)
如果您需要遍历整个列表,但只需要索引:
for i, _ in enumerate(lst):
    print(i)

如果您要遍历整个列表,但不需要索引或数据:

for _ in lst:
    print("hello")

如果你正在遍历一个列表的一部分:

for x in lst[:-5]:
    print(x)

等等等等。

虽然我不确定为什么你想要迭代列表的部分,但这似乎很奇怪。我很想听听你的用例,因为它可能可以改进。

看了一下你现在发布的代码,@Metareven有一个很好的解决方案——按你想要处理的大小将列表分块迭代。


2

你的代码看起来并不糟糕,但如果你想每次迭代3个元素,我建议使用for循环,将i变量每次增加3,像这样:

for i in range(0,len(s),3):
  row = str(s[i]) + " " + str(s[i+1]) + " " + str(s[i+2])
  print(row)

0

看起来您想使用一种滑动窗口方式遍历集合。这种情况下,我建议使用 itertools.islice

>>> from itertools import islice
>>> 
>>> s = [i for i in range(10)] # Or whatever iterable you have
>>> 
>>> iter1 = islice(s, 1, None)
>>> iter2 = islice(s, 2, None)
>>> 
>>> for a, b, c in zip(s, iter1, iter2):
...     print('[{}, {}, {}]'.format(a, b, c))
... 
[0, 1, 2]
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
[6, 7, 8]
[7, 8, 9]

如果您不介意复制数据,可以使用传统的切片符号:

>>> s = [i for i in range(10)] # Again, this could be any iterable
>>> 
>>> for a, b, c in zip(s, s[1:], s[2:]):
...     print('[{}, {}, {}]'.format(a, b, c))
... 
[0, 1, 2]
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
[6, 7, 8]
[7, 8, 9]

0

使用itertools的解决方案:

import itertools

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    args = [iter(iterable)] * n
    return itertools.zip_longest(*args, fillvalue=fillvalue)

s = list(range(10))

for row in list(grouper(s, 3)):
    print(row)

提供

(0, 1, 2)
(3, 4, 5)
(6, 7, 8)
(9, None, None)

[Program finished]

其他想法


# if you're printing it straight away, you might as well
print(*s[3*i: 3*i+3], sep=' ')

for i in range(0, len(s), 3):
    print(' '.join(s[i:i + 3])

# so you can kind of cheat with numpy for this:

for row in numpy.array(s).reshape((3,-1)):
     print(row)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接