类型错误:列表索引必须是整数或切片,不能是字符串。

98
我有两个列表,想要将它们合并成一个数组,并最终将其放入CSV文件中。
我该如何避免这个错误:
def fill_csv(self, array_urls, array_dates, csv_file_path):
    result_array = []
    array_length = str(len(array_dates))

    # We fill the CSV file
    file = open(csv_file_path, "w")
    csv_file = csv.writer(file, delimiter=';', lineterminator='\n')

    # We merge the two arrays in one

    for i in array_length:
        result_array[i][0].append(array_urls[i])
        result_array[i][1].append(array_dates[i])
        i += 1

    csv_file.writerows(result_array)

并获取:

  File "C:\Users\--\gcscan.py", line 63, in fill_csv
    result_array[i][0].append(array_urls[i])
TypeError: list indices must be integers or slices, not str

我的计数器怎么能工作?


5
你明确将 array_length 定义为字符串,所以 i 是一个字符而不是数字... - jonrsharpe
1
哎呀,我看错方向了...谢谢!! - Arthur C-G
2
当我认为我正在解析 {thisthing} 时,实际上我正在解析 [{thisthing}],例如,我试图处理一个字典,但实际上我正在处理一个列表。动态类型很棒。 - Tommy
7个回答

72

首先,array_length 应该是一个整数而不是字符串:

array_length = len(array_dates)

第二点,你的for循环应该使用range构建:

for i in range(array_length):  # Use `xrange` for python 2.

第三,i 将自动增加,因此请删除以下行:

i += 1
请注意,如果两个列表的长度相同,也可以使用zip将它们组合在一起:
import csv

dates = ['2020-01-01', '2020-01-02', '2020-01-03']
urls = ['www.abc.com', 'www.cnn.com', 'www.nbc.com']

csv_file_patch = '/path/to/filename.csv'

with open(csv_file_patch, 'w') as fout:
    csv_file = csv.writer(fout, delimiter=';', lineterminator='\n')
    result_array = zip(dates, urls)
    csv_file.writerows(result_array)

谢谢,我不知道自动递增! :) 我的代码可以工作了,谢谢。 - Arthur C-G
没有什么魔法:i 是由 range(或 Python 3 中的 sequence)返回的列表中的一个元素。哦,顺便说一下:它们都是列表,而不是数组。 - Pynchia

17

跟进Abdeali Chandanwala上面的答案(因为声望值<50,无法评论) -

简要概述:我试图遍历一个字典列表,错误的只关注了字典中的键而不是遍历字典本身!


我在拥有以下结构的情况下遇到了相同的错误:

{
   "Data":[
      {
         "RoomCode":"10",
         "Name":"Rohit",
         "Email":"rohit@123.com"
      },
      {
         "RoomCode":"20"
         "Name":"Karan",
         "Email":"karan@123.com"
      }
   ]
}

我试图像这样将名称附加到列表中 -

接收到相同错误

通过以下方式解决了问题 -

修复了错误


13

我也遇到过同样的错误,错误在于我将列表和字典添加到了同一列表(对象)中,当我迭代字典列表并碰到一个列表类型的对象时,因为我试图访问每个字典中的键而导致此错误。

所以我必须确保只将字典对象添加到该列表中。


2

正如该错误信息所述,当使用一个字符串作为列表的索引时,就会出现此错误。大多数导致这种错误的情况可以归纳为以下几种情况。

1. 列表被用作字典

1.1. 把列表当做字典进行索引

这种情况通常发生在将JSON对象转换为Python对象时,但其中有一个嵌套在列表中的字典。如果列表中只有一个字典,则特别麻烦(也容易忽略)。在下面的示例中,'summary'关键字下的值是包含单个字典的列表。因此,如果尝试使用json['summary']['home_score']来获取主队得分,则会显示错误。

json = {
    "teams": {"home": "BOS", "away": "MIA"},
    "summary": [
        {"home_score": 0, "away_score": 0}
    ]
}

json['summary']['home_score']               # <---- TypeError: list indices must be integers or slices, not str
json['summary'][0]['home_score']            # <---- OK (returns the first item)
#              ^^^   <---- index the list here
[d['home_score'] for d in json['summary']]  # <---- OK (returns a list)

在进行HTTP请求、API调用等操作时,通常会得到非常嵌套的结果,不太明显如何处理这些数据。但是通过简单的调试步骤,例如打印数据的类型、长度等信息,通常可以展示如何处理它们。
print(type(json['summary']))                # <class 'list'>    <---- check the data type
print(len(json['summary']))                 #                   <---- check length of data
print(type(json['summary'][0]))             # <class 'dict'>    <---- check type of item

1.2. 将值分配给列表,就像它是字典一样

另一个常见的错误是初始化一个列表,但尝试使用键为其分配值。初始化可能是动态的,后来并不清楚它实际上是一个列表。例如,在以下情况下,d 被初始化为一个列表,但尝试向其中添加键值对。解决方案是初始化一个空字典 {} 而不是 []

d = []
d['key'] = 1                                # <---- TypeError


d = {}
d['key'] = 1                                # <---- OK

1.3. pandas dataframe被意外地转换为列表

一种常见的更改pandas dataframe列标签的方法是直接将一个字符串列表分配给pd.DataFrame.columns属性,以成为新标签。如果将其分配给pd.DataFrame,则整个dataframe将被替换为列表,并且不再能够通过标签访问列。

import pandas as pd
df = pd.DataFrame([range(4), range(4)])
df = ['A', 'B', 'C', 'D']
df['A']                                     # <---- TypeError


df = pd.DataFrame([range(4), range(4)])
df.columns = ['A', 'B', 'C', 'D']
# ^^^^^^^^  <---- assign column labels here
df['A']                                     # <---- OK

2. 字符串被当作整数使用

2.1. 使用input()索引列表

一个非常常见的错误是尝试使用用户输入的值来索引列表。因为input()返回一个字符串,所以在用它来索引列表之前必须将其转换为整数。

lst = ['a', 'b', 'c']
index = input()

lst[index]                                  # <---- TypeError: list indices must be integers or slices, not str
lst[int(index)]                             # <---- OK

2.2. 使用字符串列表索引列表

另一个常见的错误是循环遍历列表并使用列表项来索引列表。Python 的 for 循环类似于 Perl 的 foreach,因为循环是在一组项目上进行的。由于列表已经被迭代,所以没有必要再次对其进行索引,因此解决方案是直接使用该项进行需要完成的操作。或者循环遍历使用列表长度构造的 range 对象。

lst = ['a', 'b', 'a', 'd']

lst['a']                                    # <---- TypeError
lst[lst.index('a')]                         # <---- OK

这个错误很可能在一个动态创建lst的循环中更频繁地发生。

for i in lst:
    if lst[i] == 'b':                       # <---- TypeError
        pass

for i in lst:
    if i == 'b':                            # <---- OK
        pass
    
for i in range(len(lst)):                   # <---- OK
    if lst[i] == 'b':
        pass

注意: 这是 OP 的情况。使用字符串在列表中进行循环使用了字符串索引。解决方法是循环一个范围对象。


2
在我的情况下,我试图更改一个字典键的值,但由于我的字典在for循环中,并且被更改为list类型,所以我得到了相同的错误。
for value in source_list:
    my_dict['my_key']=some_val
    dict=list(mydict)
    exctraction0 = dict[0]

我通过确保dict的类型保持不变,通过在每次迭代后进行深拷贝重新初始化来解决了这个问题(这就是这个用例的全部内容)。

copy_dict = copy.deepcopy(my_dict)
for value in source_list:
    my_dict =copy.deepcopy(copy_dict)
    my_dict['my_key']=some_val
    dict=list(mydict)
    exctraction0 = dict[0]

1

我在Python中对一个函数进行重载时遇到了这个错误,其中一个函数包装了另一个函数:

def getsomething(build_datastruct_inputs : list[str]) -> int:
      # builds datastruct and calls getsomething
      return getsomething(buildit(build_datastruct_inputs))

def getsomething(datastruct : list[int]) -> int:
      # code
      # received this error on first use of 'datastruct'

修复方法是不重载并使用唯一的方法名称。
def getsomething_build(build_datastruct_inputs : list[str]) -> int:
      # builds datastruct and calls getsomething
      return getsomething_ds(buildit(build_datastruct_inputs))

def getsomething_ds(datastruct : list[int]) -> int:
      # code
      # works fine again regardless of whether invoked directly/indirectly

另一种解决方法是使用Python multipledispatch包,它允许您进行重载并为您解决此问题。由于错误发生的位置(也没有消息)与原因不符,有点令人困惑。我以为Python本身支持重载,但现在我已经学到了它需要用户更多的工作来实现。

0
我是通过谷歌搜索到这里来的,我的错误发生在代码中,例如:
a = ["b"]
del a["b"]

错误:
del a["b"]
TypeError: list indices must be integers or slices, not str

这是因为从列表中删除元素只能使用列表中的索引或切片。
不过,应该使用
a.remove("b")

请注意,这现在是一个O(n)的操作。

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