Python 创建数组后,如何正确遍历CSV文件中的行数组?

Python 创建数组后,如何正确遍历CSV文件中的行数组?,python,csv,for-loop,valueerror,Python,Csv,For Loop,Valueerror,非常抱歉,如果以前回答过这个问题,但我搜索了StackOverflow,找不到解决问题的明确解决方案 我有一个名为“myFile.CSV”的CSV文件 文件以逗号(“,”)分隔 第一行包含列标题,而所有后续行都是数据行 我打开并读取CSV文件,将每一行分配给一个名为“myArray”的数组,该数组将在以后用于不同的用途 with open("..\dirX\myFile.csv", 'rb') as fileHandle: myArray = [] for row in cs

非常抱歉,如果以前回答过这个问题,但我搜索了StackOverflow,找不到解决问题的明确解决方案

我有一个名为“myFile.CSV”的CSV文件

  • 文件以逗号(“,”)分隔
  • 第一行包含列标题,而所有后续行都是数据行
我打开并读取CSV文件,将每一行分配给一个名为“myArray”的数组,该数组将在以后用于不同的用途

with open("..\dirX\myFile.csv", 'rb') as fileHandle:
    myArray = []
    for row in csv.reader(fileHandle, delimiter=','):
        myArray.append(row)
我可以成功打印阵列中的单个行

print myArray[0]    # Works fine!  Prints header row.
print myArray[1]    # Works fine!  Prints first data row.
然而,当我试图循环通过从CSV文件创建的数组来提取每一行时,我失败了。for循环代码如下所示

for idx, row in myArray:  # <--- This where the error message points to
    print 'Index = ' + str(idx)
    print row

我的问题:究竟为什么会发生这种情况,以及纠正此问题的最佳方法是什么

您的错误意味着变量名多于实际值

例如:

lst = [1,2]
a,b = lst # <-- this is ok

a,b,c = lst # error 
以防您要更改元素

res = []
for idx, row in enumerate(myArray): 
  print 'Index = ' + str(idx)
  print row
  #do change
  res.append(changed_row)

列表的行为与任何其他序列wrt/iterations没有区别:您只获取项目,而不是索引(就像在
csv.reader上迭代时一样,您只获取行,而不是索引)

如果您想同时拥有索引和项目,可以使用
enumerate()

更新:


因为它是枚举的,“项”不是不可变的吗?如果我想在以后更改其数据(例如,替换文本字符串),该怎么办

迭代并不能使任何东西或多或少地可变。一个对象是可变的(并且在
for
循环体中对其进行突变的工作原理与在循环外部相同),或者它不是可变的

你似乎被变异和重新绑定之间的区别弄糊涂了。下面是一个包含可变对象列表的示例:

>>> data = [dict(a=i) for i in xrange(3)]
>>> data
[{'a': 0}, {'a': 1}, {'a': 2}]
>>> for item in data:
...     item["b"] = item["a"] + 42
... 
>>> data
[{'a': 0, 'b': 42}, {'a': 1, 'b': 43}, {'a': 2, 'b': 44}]
正如您所看到的,这些项是完全可变的

现在,您不能使用不可变对象列表来实现这一点,这不是因为
for
循环(在这里使用
enuenerate
与否无关),而是因为不可变对象是不可变的。让我们首先在
for
循环外检查此项:

>>> s = "foo 1"
>>> s.replace("1", "2")
'foo 2'
>>> s
'foo 1'
>>> data = ["aaa", "bbb", "ccc"]
>>> item = data[0]
>>> item
'aaa'
>>> item = "AAA"
>>> item
'AAA'
>>> data
['aaa', 'bbb', 'ccc']
如您所见,
str.replace()
返回一个新字符串,并保持原始字符串不变(当然,字符串是不可变的)。如果希望
s
成为“foo 2”,则必须重新绑定
s
,使其指向另一个字符串:

请注意,重新绑定变量不会影响指向同一对象的其他变量:

>>> s1 = "aaa"
>>> id(s1)
139792880524584
>>> s2 = "bbb"
>>> id(s2)
139792880522104
>>> s1 = "aaa"
>>> s1
'aaa'
>>> id(s1)
139792880524584
>>> s2 = s1
>>> s2
'aaa'
>>> id(s2)
139792880524584
>>> s2 is s1
True
>>> # now let's rebind s1:    
>>> s1 = "bbb"
>>> s1
'bbb'
>>> id(s1)
139792880522104
>>> s2
'aaa'
>>> id(s2)
139792880524584
>>> s2 is s1
False
>>> 
因此,从技术上讲,重新绑定迭代变量(
item
在我们上面的代码片段中)是可行的(这个变量是response),但这不会影响列表或上面迭代的任何内容(就像重新绑定
s1
不会影响
s2
):

因此,如果您有一个字符串列表,并且希望在适当的位置更新该列表,则必须对该列表本身进行变异-这也需要具有匹配的索引,这是使用
枚举
获得的:

for index, item in enumerate(somelist):
    print("item at {} is {}".format(index, item))
>>> data = ["aaa", "bbb", "ccc"]
>>> for index, item in enumerate(data):
...     data[index] = item.upper()
... 
>>> data
['AAA', 'BBB', 'CCC']
请注意,这里我们不是重新绑定迭代变量,而是对
数据
列表本身进行变异。对于
循环,其工作原理与不使用时相同:

>>> s = "foo 1"
>>> s.replace("1", "2")
'foo 2'
>>> s
'foo 1'
>>> data = ["aaa", "bbb", "ccc"]
>>> item = data[0]
>>> item
'aaa'
>>> item = "AAA"
>>> item
'AAA'
>>> data
['aaa', 'bbb', 'ccc']
与:

>>> data = ["aaa", "bbb", "ccc"]
>>> data[0] = "AAA"
>>> data
['AAA', 'bbb', 'ccc']
>>> 

因为它是枚举的,“项”不是不可变的吗?如果我以后想更改它的数据(例如,替换文本字符串),该怎么办?@InformationTechnology:尝试提供的解决方案,看看它是否使
不可变。实验的结果是什么?真棒的解释。谢谢。枚举行不是使它完全不可变/不可更改吗?以后如何更改行中的值?例如,如果我想稍后替换行中的字符串,该怎么办?@InformationTechnology here is document。它不会改变任何东西。@InformationTechnology顺便说一句,如果您想在迭代过程中更改元素,最好创建另一个list@galaxyan没有任何东西可以阻止您更改现有列表。您通常希望避免的是在迭代同一序列时向序列中添加/删除,因为它会弄乱迭代器。。。
>>> data = ["aaa", "bbb", "ccc"]
>>> item = data[0]
>>> item
'aaa'
>>> item = "AAA"
>>> item
'AAA'
>>> data
['aaa', 'bbb', 'ccc']
>>> data = ["aaa", "bbb", "ccc"]
>>> data[0] = "AAA"
>>> data
['AAA', 'bbb', 'ccc']
>>>