为什么我会看到“TypeError: 字符串索引必须是整数”?
我正在学习Python,同时想把GitHub上的问题整理成易读的格式。根据这个链接的建议:我该如何将JSON转换为CSV?,我写了以下代码:
import json
import csv
f = open('issues.json')
data = json.load(f)
f.close()
f = open("issues.csv", "wb+")
csv_file = csv.writer(f)
csv_file.writerow(["gravatar_id", "position", "number"])
for item in data:
csv_file.writerow([item["gravatar_id"], item["position"], item["number"]])
这里的“issues.json”是包含我GitHub问题的JSON文件。当我尝试运行这段代码时,我遇到了以下错误:
TypeError: string indices must be integers
我这里缺少了什么呢?所谓的“字符串索引”指的是什么?
这是我JSON内容的一部分:
{"issues": [{"gravatar_id": "44230311a3dcd684b6c5f81bf2ec9f60", "position": 2.0, "number": 263...
10 个回答
切片表示法中的类型错误 str[a:b]
简短回答
在 str[a:b]
中,两个索引 a
和 b
之间要用冒号 :
,而不是逗号 ,
:
my_string[0,5] # wrong ❌
my_string[0:5] # correct ✅
详细回答
在处理字符串和切片表示法(这是一种常见的序列操作)时,可能会遇到TypeError
错误,提示说索引必须是整数,即使它们看起来确实是整数。
例子
>>> my_string = "Hello, World!"
>>> my_string[0,5]
TypeError: string indices must be integers
我们显然是给切片表示法传了两个整数,对吧?那这里的问题是什么呢?
这个错误可能会让人很沮丧,尤其是在学习Python的初期,因为错误信息有点误导。
解释
当我们调用 my_string[0,5]
时,实际上是隐式地将一个包含两个整数的元组
传给了切片表示法。0,5
和 (0,5)
计算出来的结果是一样的——即使没有括号。为什么会这样呢?
其实,单单一个结尾的逗号 ,
就足够让Python解释器将某个东西当作元组来处理:
>>> my_variable = 0,
>>> type(my_variable)
<class 'tuple'>
所以这次我们所做的,显式地说:
>>> my_string = "Hello, World!"
>>> my_tuple = 0, 5
>>> my_string[my_tuple]
TypeError: string indices must be integers
现在,至少错误信息是有道理的。
解决方案
我们需要用冒号 :
替换掉逗号 ,
,这样才能正确分隔两个整数,而不是让它们被解释成一个元组
:
>>> my_string = "Hello, World!"
>>> my_string[0:5]
'hello'
一个更清晰、更有帮助的错误信息可能是这样的:
TypeError: string indices must be integers not tuple
^^^^^
(actual type here)
好的错误信息应该直接告诉用户他们做错了什么!有了这样的信息,找到问题的根源并解决它会容易得多——你也就不需要来这里了。
所以下次,当你负责编写错误描述信息时,记得这个例子,给错误信息添加原因(或其他有用的信息)!帮助其他人(或者将来的自己)理解哪里出了问题。
总结经验
- 切片表示法使用冒号
:
来分隔索引(以及步长范围,比如str[from:to:step]
) - 元组是用逗号
,
定义的(例如t = 1,
) - 给错误信息添加一些信息,帮助用户理解哪里出错了
变量 item
是一个字符串。索引的样子是这样的:
>>> mystring = 'helloworld'
>>> print mystring[0]
'h'
上面的例子使用了字符串的 0
索引来指代第一个字符。
字符串不能像字典那样使用字符串作为索引。所以这样做是行不通的:
>>> mystring = 'helloworld'
>>> print mystring['stringindex']
TypeError: string indices must be integers
item
在你的代码中很可能是一个字符串;字符串的索引就是方括号里的内容,比如 gravatar_id
。所以我建议你先检查一下你的 data
变量,看看里面到底有什么。我猜 data
是一个字符串的列表(或者至少包含一个字符串的列表),但它应该是一个字典的列表。