【问题标题】:How to read Python reader iteratively outside of for construct?如何在 for 构造之外迭代地阅读 Python 阅读器?
【发布时间】:2017-08-16 08:48:37
【问题描述】:

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

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

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

问题很笼统,我想明白,能留在in之前是什么意思。在 Java 中,这意味着是 Iterable 接口,我可以很容易地找到它的文档并知道我可以用它做什么。

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

我可以选择其他吗?

【问题讨论】:

  • 我怎么知道reader() 返回迭代器? for 中的用法暗示了这一点?
  • 是的,for ... in X 暗示 X 是某种迭代器。 Python 有相当丰富的东西可以迭代。
  • Xfor whatever in X 中可用意味着X 是一个可迭代。这可能是一个迭代器(在 Java 中不算作可迭代),也可能是某种可重用的可迭代对象,例如列表或 Python 3 范围对象。
  • rder 本质上不是迭代器;它只是一个迭代器,因为 Python 可以使用文本文件(以及许多其他返回字符串的对象)作为迭代器。

标签: python csv iterator


【解决方案1】:

csv.reader 返回一个iterator

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

所以这个:

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]]))

【讨论】:

  • Bleh,SO Docs。仅查看链接指向的第一段,我已经可以看到几个错误。 real Python docs 不是最好的,但通常比这更好。
【解决方案2】:

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() 的结果

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-08
    • 2020-11-26
    • 2021-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-21
    相关资源
    最近更新 更多