如何在构造之外迭代地阅读Python阅读器?

时间:2017-03-23 16:44:43

标签: python csv iterator

我编写了这段代码并按顺序打印了行:

with open(filename, 'r') as csvfile:
    rder = csv.reader(csvfile, delimiter=',')
    for row in rder:
        print(row)

是否可以使用rderhasNext方式访问next,即没有for构造?例如,如何跳过第一行?

问题是一般的,我想了解,能够在in之前停留是什么意思。在Java中,这意味着具有Iterable界面,我可以轻松找到它的文档,并知道我可以用它做什么。

在Python中,没有关于reader函数返回的内容的信息,我不知道除了what is written in example之外我能用它做什么。并且该示例仅用于for

我可以选择其他选择吗?

2 个答案:

答案 0 :(得分:3)

csv.reader会返回iterator

迭代器可以通过forin循环中使用:

所以这个:

import csv
rder = csv.reader(my_csv(), delimiter=' ')
for row in rder:
    print(row)

给出:

['A', 'header', 'row']
['some', 'data']
['some', 'more', 'data']
['A', 'footer']

可以使用next()在for循环中读取迭代器:

如果我们需要在for循环中使用一行,我们可以这样做:

rder = csv.reader(my_csv(), delimiter=' ')
for row in rder:
    print(row)
    print('Grabbed one:', next(rder))

给予:

['A', 'header', 'row']
Grabbed one: ['some', 'data']
['some', 'more', 'data']
Grabbed one: ['A', 'footer']

迭代器也可以在for循环之外使用:

rder = csv.reader(my_csv(), delimiter=' ')
print('first one:', next(rder))
print('second one:', next(rder))
for row in rder:
    print(row)

会给:

first one: ['A', 'header', 'row']
second one: ['some', 'data']
['some', 'more', 'data']
['A', 'footer']

测试数据:

from io import StringIO

def my_csv():
    return StringIO('\n'.join([x.strip() for x in u"""
        A header row
        some data
        some more data
        A footer
    """.split('\n')[1:-1]]))

答案 1 :(得分:1)

csv.reader返回基于底层对象迭代器协议的迭代器。如果底层对象不支持迭代,它将不能用作迭代器。

如果您使用文本文件,那么该文件基于导致next为文本文件(通常是\n序列而不是总是... ...)的原因而导致的文本

可以编写一个不基于for协议的循环Python。相反,您使用try/except并捕获StopIteration例外:

with open('file.csv') as csvfile:
    rder = csv.reader(csvfile)
    while True:
        try:
            row=next(rder)  
            print row
        except StopIteration:
            break   

但具体来说,要获得标题,最好这样做:

with open('file.csv') as csvfile:
    rder = csv.reader(csvfile)
    header=next(rder)
    print header
    for row in rder:
        print row

或者,使用Python3,您可以将其缩短为:

with open('/tmp/file.csv') as csvfile:
    rder = csv.reader(csvfile)
    header, *rows=[row for row in rder]

但是你也可以使用非文件对象,比如带有csv的字符串和由单独的分隔符分隔的记录:

>>> s='A,B,C|1,2,3|4,5,6'
>>> import csv
>>> for row in csv.reader(s.split("|")):
...    print row
... 
['A', 'B', 'C']
['1', '2', '3']
['4', '5', '6']

在这种情况下,next正在转移到.split()

结果的下一个列表元素