4.10 �列上索引值迭代¶

问题¶

你想在迭代一个�列的�时跟踪正在被处�的元素索引。

解决方案¶

内置的 enumerate() 函数�以很好的解决这个问题:

>>> my_list = ['a', 'b', 'c']
>>> for idx, val in enumerate(my_list):
...     print(idx, val)
...
0 a
1 b
2 c

为了按传统行�输出(行�从1开始),你�以传递一个开始�数:

>>> my_list = ['a', 'b', 'c']
>>> for idx, val in enumerate(my_list, 1):
...     print(idx, val)
...
1 a
2 b
3 c

这�情况在你�历文件时想在错误消�中使用行�定�时候�常有用:

def parse_data(filename):
    with open(filename, 'rt') as f:
        for lineno, line in enumerate(f, 1):
            fields = line.split()
            try:
                count = int(fields[1])
                ...
            except ValueError as e:
                print('Line {}: Parse error: {}'.format(lineno, e))

enumerate() 对于跟踪�些值在列表中出现的�置是很有用的。 所以,如果你想将一个文件中出现的��映射到它出现的行�上去,�以很容易的利用 enumerate() �完�:

word_summary = defaultdict(list)

with open('myfile.txt', 'r') as f:
    lines = f.readlines()

for idx, line in enumerate(lines):
    # Create a list of words in current line
    words = [w.strip().lower() for w in line.split()]
    for word in words:
        word_summary[word].append(idx)

如果你处�完文件�打� word_summary ,会�现它是一个字典(准确�讲是一个 defaultdict ), 对于�个��有一个 key ,�个 key 对应的值是一个由这个��出现的行�组�的列表。 如果�个��在一行中出现过两次,那么这个行�也会出现两次, �时也�以作为文本的一个简�统计。

讨论¶

当你想�外定义一个计数��的时候,使用 enumerate() 函数会更加简�。你�能会�下�这样写代�:

lineno = 1
for line in f:
    # Process line
    ...
    lineno += 1

但是如果使用 enumerate() 函数�代替就显得更加优雅了:

for lineno, line in enumerate(f):
    # Process line
    ...

enumerate() 函数返回的是一个 enumerate 对象实例, 它是一个迭代器,返回连续的包�一个计数和一个值的元组, 元组中的值通过在传入�列上调用 next() 返回。

还有一点�能并�很��,但是也值得注�, 有时候当你在一个已�解压�的元组�列上使用 enumerate() 函数时很容易调入陷阱。 你得�下�正确的方�这样写:

data = [ (1, 2), (3, 4), (5, 6), (7, 8) ]

# Correct!
for n, (x, y) in enumerate(data):
    ...
# Error!
for n, x, y in enumerate(data):
    ...