为什么我会看到“类型错误:字符串索引必须是整数”?
我正在学习 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...
I'm playing with both learning Python and am trying to get GitHub issues into a readable form. Using the advice on How can I convert JSON to CSV?, I came up with this:
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"]])
Where "issues.json" is the JSON file containing my GitHub issues. When I try to run that, I get
TypeError: string indices must be integers
What am I missing here? Which are the "string indices"?
Here's a bit of my JSON content:
{"issues": [{"gravatar_id": "44230311a3dcd684b6c5f81bf2ec9f60", "position": 2.0, "number": 263...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
变量
item
是一个字符串。索引如下所示:上面的示例使用字符串的
0
索引来引用第一个字符。字符串不能有字符串索引(就像字典可以一样)。所以这行不通:
The variable
item
is a string. An index looks like this:The above example uses the
0
index of the string to refer to the first character.Strings can't have string indices (like dictionaries can). So this won't work:
item
很可能是代码中的字符串;字符串索引是方括号中的索引,例如gravatar_id
。因此,我首先检查您的data
变量,看看您在那里收到了什么;我猜想data
是一个字符串列表(或者至少是一个包含至少一个字符串的列表),而它应该是一个字典列表。item
is most likely a string in your code; the string indices are the ones in the square brackets, e.g.,gravatar_id
. So I'd first check yourdata
variable to see what you received there; I guess thatdata
is a list of strings (or at least a list containing at least one string) while it should be a list of dictionaries.切片表示法的类型错误
str[a:b]
简短回答
使用冒号
:
而不是逗号,
位于str[a:b]
中的两个索引a
和b
之间:长答案
当使用 字符串和切片符号(常见序列操作),可能会引发
TypeError
,指出索引必须是整数,即使它们显然是整数。示例
显然,我们将索引的两个整数传递给了切片表示法,对吧?那么这里有什么问题呢?
这个错误可能会非常令人沮丧——尤其是在刚开始学习Python时——因为错误消息有点误导。
说明
当我们调用
my_string[0,5]
时,我们隐式地将两个整数的tuple
传递给切片表示法。0,5
的计算结果与(0,5)
相同 - 即使没有括号。为什么呢?尾随逗号
,
实际上足以让 Python 解释器将某些内容作为元组进行计算:那么我们这次明确做了什么:
现在,至少错误消息是有意义的。
解决方案
我们需要将逗号
,
替换为冒号:
来正确分隔两个整数,而不是让它们解释为元组:更清晰、更有用的错误消息可能类似于:
一条好的错误消息应该直接向用户显示他们做错了什么!有了此类信息,就可以更容易地找到根本原因并解决问题 - 而且您不必来到这里。
因此,下次,当您发现自己负责编写错误描述消息时,请提醒自己此示例并将原因(或其他有用的信息)添加到错误消息中!帮助其他人(甚至可能是未来的你)了解出了什么问题。
经验教训
:
分隔其索引(和步长范围,即str[from:to:step]
)定义,
(即t = 1,
)TypeError for Slice Notation
str[a:b]
Short Answer
Use a colon
:
instead of a comma,
in between the two indicesa
andb
instr[a:b]
:Long Answer
When working with strings and slice notation (a common sequence operation), it can happen that a
TypeError
is raised, pointing out that the indices must be integers, even if they obviously are.Example
We obviously passed two integers for the indices to the slice notation, right? So what is the problem here?
This error can be very frustrating - especially at the beginning of learning Python - because the error message is a little bit misleading.
Explanation
We implicitly passed a
tuple
of two integers to the slice notation when we calledmy_string[0,5]
.0,5
evaluates to the same tuple as(0,5)
does - even without the parentheses. Why though?A trailing comma
,
is actually enough for the Python interpreter to evaluate something as a tuple:So what we did there, this time explicitly:
Now, at least, the error message makes sense.
Solution
We need to replace the comma
,
with a colon:
to separate the two integers correctly, not having them interpreted as atuple
:A clearer and more helpful error message could have been something like:
A good error message should show the user directly what they did wrong! With this kind of information it would have been much more easier to find the root cause and solve the problem - and you wouldn't have had to come here.
So next time, when you find yourself responsible for writing error description messages, remind yourself of this example and add the reason (or other useful information) to error message! Help other people (or maybe even your future self) to understand what went wrong.
Lessons learned
:
to separate its indices (and step range, i.e.,str[from:to:step]
),
(i.e.,t = 1,
)data
是一个dict
对象。因此,像这样迭代它:Python 2
Python 3
data
is adict
object. So, iterate over it like this:Python 2
Python 3
我对 Pandas 也有类似的问题,您需要使用 iterrows() 函数来迭代 Pandas 数据集iterrows 的 Pandas 文档
请注意,您需要处理函数返回的数据集中的索引。
I had a similar issue with Pandas, you need to use the iterrows() function to iterate through a Pandas dataset Pandas documentation for iterrows
note that you need to handle the index in the dataset that is also returned by the function.
正如消息所述,当使用除整数以外的任何内容来索引字符串时,就会发生此错误。 大多数导致此错误的情况可以总结为以下情况(以及可能的解决方案)。
字典上的循环 字典
上的 for 循环是对其键的 for 循环,而不是其值的 for 循环,因此迭代它来访问值可能会导致此错误。这种情况很常见,尤其是在字典嵌套严重的情况下。
例如,在OP的例子中,字典中的值是包含所需键值对的字典列表。因此,要迭代
issues
键下的列表,请通过data['issues']
访问它并循环遍历它。还有一个例子可以说明这一点。这里尝试在循环外部字典的同时访问内部字典。如果我们循环外部字典的 dict_items,我们就可以循环内部字典,因为现在我们可以访问它们。
dict_items
循环字典中的值通过其键进行访问。但是,当目的是简单地访问字典中的值但使用 for 循环时,可能会出现此错误。如果在字典上调用
.items()
,则无需再次通过键访问值/项目;只需按原样使用该值即可。未反序列化的 json
这种情况通常发生在 json 对象尚未转换为 Python 对象但像字典一样使用时。在下面的示例中,
'data'
是一个json对象,因此如果您尝试通过data['key1']<获取
'key1'
下的值< /code>,它会显示错误。当发出 http 请求、API 调用等时,结果通常是非常嵌套的,并且如何处理该数据不是很明显,但通过简单的调试步骤(例如打印数据的类型、长度等)通常会显示如何处理它。
Python 字典的字符串文字
有时,数据不是 json 对象,而只是 Python 对象的字符串表示形式,在这种情况下,
ast.literal_eval()
可能有助于解析它。如果这些字符串位于列表或 pandas DataFrame 或其他一些集合中,而这些集合中并不清楚它们是字符串,则这种情况尤其常见。使用
input()
为字符串建立索引一个常见的错误是尝试使用用户输入中的值来为字符串建立索引。由于
input()
返回一个字符串,因此在用于索引字符串之前必须将其转换为整数。列表/元组/pandas 系列等用于索引字符串
另一种情况(此处前两个答案部分涵盖)是使用除整数之外的任何内容来索引字符串。解决方案是对字符串进行切片或循环索引列表/系列并索引字符串。
As the message says, this error occurs when anything but an integer is used to index a string. Most of the cases leading to this error can be summarized in the following cases (along with a possible solution).
A loop over a dict
A for-loop over a dictionary is a for-loop over its keys, not its values, so iterating over it to access the values might result in this error. This is common especially if the dictionary is heavily nested.
For example, in the OP's case, a value in a dictionary was a list of dictionaries which contained the key-value pairs needed. So to iterate over the list under the
issues
key, access it bydata['issues']
and loop over it.Yet another example to illustrate the point. Here an attempt to access the inner dictionary while looping over the outer dictionary was made. If we loop over
dict_items
of the outer dictionary, we could loop over the inner dictionary because now we have access to them.A loop over
dict_items
A value in a dictionary is accessed by its key. However, when the intention was to simply access values in a dictionary but a for-loop over utilizes instead, this error may show up. If
.items()
is called on a dictionary, there's no need to access the value/item by key again; simply use the value as is.Un-deserialized json
This case commonly occurs when a json object is yet to be converted into a Python object but is used as if it were a dictionary. In the example below,
'data'
is a json object, so if you try to get the value under'key1'
bydata['key1']
, it will show an error.When making a http request, an API call, etc. the outcome is usually very nested and it's not very obvious how to handle that data but with a simple debugging step such as printing the type, length etc. of the data usually shows how to handle it.
String literal of a Python dictionary
Sometimes the data is not a json object but just a string representation of a Python object, in which case
ast.literal_eval()
could be useful to parse it. This case is especially common if these strings are in a list or a pandas DataFrame or some other collection where it's not visibly clear that they are strings.Index a string using an
input()
A common mistake is when one tries to index a string using a value from a user input. Because
input()
returns a string, it must be converted into an integer before being used to index a string.A list / tuple / pandas Series etc. is used to index a string
Another case (that is partially covered in the top two answers here) is to index a string using anything but an integer. The solution is either to slice a string or loop over the list / Series of indices and index the string.
根据经验,当我在 Python 中收到此错误时,我将函数签名与函数执行进行比较。
例如:
因此,如果我使用以错误顺序放置的参数调用此函数,并将列表作为第二个参数传递,字符串作为第一个参数传递:
该函数将尝试迭代
parent_id
string 而不是 file_list ,并且它期望将索引视为指向字符串中特定字符的整数,而不是字符串索引(title
或id
)。这将导致
TypeError:字符串索引必须是整数
错误。由于其动态特性(与 Java、C# 或 Typescript 等语言相反),Python 不会通知您此语法错误。
As a rule of thumb, when I receive this error in Python I compare the function signature with the function execution.
For example:
So if I'll call this function with parameters placed in the wrong order and pass the list as the 2nd argument and a string as the 1st argument:
The function will try to iterate over the
parent_id
string instead offile_list
and it will expect to see the index as an integer pointing to the specific character in string and not an index which is a string (title
orid
).This will lead to the
TypeError: string indices must be integers
error.Due to its dynamic nature (as opposed to languages like Java, C# or Typescript), Python will not inform you about this syntax error.
对我来说,当我尝试获取每个客户端的
id
循环抛出函数getClientByPoweruser
返回的结果时,我会遇到此错误;忘记这个函数返回一个带有
success
和data
键的对象而不是客户端项目列表,这就是我收到错误的原因:
要解决这个问题,我只需循环抛出
result['data']
数组,其中真正包含客户端列表:For me I go this error when I tried to get the
id
of each clients looping throw the result returned by the functiongetClientByPoweruser
;forgetting that this function returns an object with
success
anddata
keys rather then list of clients item,that is why I got the error:
to fix this I had simply to loop throw
result['data']
array which really contains the list of clients:如果缺少逗号,就会发生这种情况。当我有一个双元组列表时,我遇到了这个问题,每个元组都包含第一个位置的字符串和第二个位置的列表。在一种情况下,我错误地省略了元组的第一个组件后面的逗号,并且解释器认为我正在尝试索引第一个组件。
This can happen if a comma is missing. I ran into it when I had a list of two-tuples, each of which consisted of a string in the first position, and a list in the second. I erroneously omitted the comma after the first component of a tuple in one case, and the interpreter thought I was trying to index the first component.
将小写字母转换为大写字母:
错误:
解决方案:
Converting the lower case letters to upper:
Error :
Solution :