为什么我会看到“类型错误:字符串索引必须是整数”?

发布于 2024-11-09 07:29:41 字数 907 浏览 0 评论 0原文

我正在学习 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

別甾虛僞 2024-11-16 07:29:41

变量 item 是一个字符串。索引如下所示:

>>> mystring = 'helloworld'
>>> print mystring[0]
'h'

上面的示例使用字符串的 0 索引来引用第一个字符。

字符串不能有字符串索引(就像字典可以一样)。所以这行不通:

>>> mystring = 'helloworld'
>>> print mystring['stringindex']
TypeError: string indices must be integers

The variable item is a string. An index looks like this:

>>> mystring = 'helloworld'
>>> print mystring[0]
'h'

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:

>>> mystring = 'helloworld'
>>> print mystring['stringindex']
TypeError: string indices must be integers
冬天旳寂寞 2024-11-16 07:29:41

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 your data variable to see what you received there; I guess that data is a list of strings (or at least a list containing at least one string) while it should be a list of dictionaries.

-残月青衣踏尘吟 2024-11-16 07:29:41

切片表示法的类型错误 str[a:b]


简短回答

使用冒号 : 而不是逗号 , 位于 str[a:b] 中的两个索引 ab 之间:

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] 时,我们隐式地将两个整数的 tuple 传递给切片表示法。 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,
  • 在错误消息中添加一些信息,以便用户了解出了什么问题

TypeError for Slice Notation str[a:b]


Short Answer

Use a colon : instead of a comma , in between the two indices a and b in str[a:b]:

my_string[0,5]  # wrong ❌
my_string[0:5]  # correct ✅

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

>>> my_string = "Hello, World!"
>>> my_string[0,5]
TypeError: string indices must be integers

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 called my_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:

>>> my_variable = 0,
>>> type(my_variable)
<class 'tuple'>

So what we did there, this time explicitly:

>>> my_string = "Hello, World!"
>>> my_tuple = 0, 5
>>> my_string[my_tuple]
TypeError: string indices must be integers

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 a tuple:

>>> my_string = "Hello, World!"
>>> my_string[0:5]
'hello'

A clearer and more helpful error message could have been something like:

TypeError: string indices must be integers not tuple
                                               ^^^^^
                                         (actual type here)

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

  • slice notation uses colons : to separate its indices (and step range, i.e., str[from:to:step])
  • tuples are defined by commas , (i.e., t = 1,)
  • add some information to error messages for users to understand what went wrong
寒冷纷飞旳雪 2024-11-16 07:29:41

data 是一个 dict 对象。因此,像这样迭代它:

Python 2

for key, value in data.iteritems():
    print key, value

Python 3

for key, value in data.items():
    print(key, value)

data is a dict object. So, iterate over it like this:

Python 2

for key, value in data.iteritems():
    print key, value

Python 3

for key, value in data.items():
    print(key, value)
要走就滚别墨迹 2024-11-16 07:29:41

我对 Pandas 也有类似的问题,您需要使用 iterrows() 函数来迭代 Pandas 数据集iterrows 的 Pandas 文档

data = pd.read_csv('foo.csv')
for index,item in data.iterrows():
    print('{} {}'.format(item["gravatar_id"], item["position"]))

请注意,您需要处理函数返回的数据集中的索引。

I had a similar issue with Pandas, you need to use the iterrows() function to iterate through a Pandas dataset Pandas documentation for iterrows

data = pd.read_csv('foo.csv')
for index,item in data.iterrows():
    print('{} {}'.format(item["gravatar_id"], item["position"]))

note that you need to handle the index in the dataset that is also returned by the function.

戏舞 2024-11-16 07:29:41

正如消息所述,当使用除整数以外的任何内容来索引字符串时,就会发生此错误。 大多数导致此错误的情况可以总结为以下情况(以及可能的解决方案)。

字典上的循环 字典

上的 for 循环是对其键的 for 循环,而不是其值的 for 循环,因此迭代它来访问值可能会导致此错误。这种情况很常见,尤其是在字典嵌套严重的情况下。

例如,在OP的例子中,字典中的值是包含所需键值对的字典列表。因此,要迭代 issues 键下的列表,请通过 data['issues'] 访问它并循环遍历它。

# the data is structured like this
data = {"issues": [
    {"gravatar_id": "a", "position": 2.0, "number": 263},
    {"gravatar_id": "b", "position": 1.0, "number": 260},
]}

# iterating over `data` would be over `data`'s keys 
# we want to loop over the list under `'issues'` key
for item in data:
    print(item["gravatar_id"], item["position"], item["number"])   # <--- TypeError

# loop over the list under `issues`
for item in data['issues']:
    print(item["gravatar_id"], item["position"], item["number"])   # <--- OK

还有一个例子可以说明这一点。这里尝试在循环外部字典的同时访问内部字典。如果我们循环外部字典的 dict_items,我们就可以循环内部字典,因为现在我们可以访问它们。

data = {
    'o1': {'i1': 'value1', 'i2': 'value2'},
    'o2': {'i1': 'valu11', 'i2': 'valu22'},
    'o3': {'i1': 'val111', 'i2': 'val222'}
}

for item in data:
    for k in data[item]:
        print(item[k])         # <---- TypeError

for i, item in data.items():
    for k in item:
        print(item[k])         # <---- OK

dict_items 循环

字典中的值通过其键进行访问。但是,当目的是简单地访问字典中的值但使用 for 循环时,可能会出现此错误。如果在字典上调用 .items() ,则无需再次通过键访问值/项目;只需按原样使用该值即可。

data = {'k1': 'value1', 'k2': 'value2', 'k3': 'value3'}

for k, item in data.items():
    print(item['k1'], item['k2'], item['k3'])      # <---- TypeError


for k, item in data.items():
    print(item)                                    # <---- OK

未反序列化的 json

这种情况通常发生在 json 对象尚未转换为 Python 对象但像字典一样使用时。在下面的示例中,'data'是一个json对象,因此如果您尝试通过data['key1']<获取'key1'下的值< /code>,它会显示错误。

import json

data = '''
{
    "key1": "value1",
    "key2": "value2"
}
'''

data['key1']               # <---- TypeError: string indices must be integers

j = json.loads(data)
j['key1']                  # <---- OK

当发出 http 请求、API 调用等时,结果通常是非常嵌套的,并且如何处理该数据不是很明显,但通过简单的调试步骤(例如打印数据的类型、长度等)通常会显示如何处理它。

print(type(data))                # <class 'str'>    <---- check the data type

Python 字典的字符串文字

有时,数据不是 json 对象,而只是 Python 对象的字符串表示形式,在这种情况下,ast.literal_eval() 可能有助于解析它。如果这些字符串位于列表或 pandas DataFrame 或其他一些集合中,而这些集合中并不清楚它们是字符串,则这种情况尤其常见。

import ast

data = "{'key1': 'value1', 'key2': 'value2'}"

data['key1']                # <---- TypeError: string indices must be integers
j = json.loads(data)        # <---- JSONDecodeError  
j = ast.literal_eval(data)
j['key1']                   # <---- OK

使用 input() 为字符串建立索引

一个常见的错误是尝试使用用户输入中的值来为字符串建立索引。由于 input() 返回一个字符串,因此在用于索引字符串之前必须将其转换为整数。

lst = 'my string'
index = input()

lst[index]                                  # <---- TypeError
lst[int(index)]                             # <---- OK

列表/元组/pandas 系列等用于索引字符串

另一种情况(此处前两个答案部分涵盖)是使用除整数之外的任何内容来索引字符串。解决方案是对字符串进行切片或循环索引列表/系列并索引字符串。

s = 'my string'
s[1,3]                         # <--- TypeError
s[[1,3]]                       # <--- TypeError
s[pd.Series([1,3])]            # <--- TypeError

s[1:3]                         # <--- OK
''.join([s[i] for i in [1,3]]) # <--- OK

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 by data['issues'] and loop over it.

# the data is structured like this
data = {"issues": [
    {"gravatar_id": "a", "position": 2.0, "number": 263},
    {"gravatar_id": "b", "position": 1.0, "number": 260},
]}

# iterating over `data` would be over `data`'s keys 
# we want to loop over the list under `'issues'` key
for item in data:
    print(item["gravatar_id"], item["position"], item["number"])   # <--- TypeError

# loop over the list under `issues`
for item in data['issues']:
    print(item["gravatar_id"], item["position"], item["number"])   # <--- OK

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.

data = {
    'o1': {'i1': 'value1', 'i2': 'value2'},
    'o2': {'i1': 'valu11', 'i2': 'valu22'},
    'o3': {'i1': 'val111', 'i2': 'val222'}
}

for item in data:
    for k in data[item]:
        print(item[k])         # <---- TypeError

for i, item in data.items():
    for k in item:
        print(item[k])         # <---- OK

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.

data = {'k1': 'value1', 'k2': 'value2', 'k3': 'value3'}

for k, item in data.items():
    print(item['k1'], item['k2'], item['k3'])      # <---- TypeError


for k, item in data.items():
    print(item)                                    # <---- OK

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' by data['key1'], it will show an error.

import json

data = '''
{
    "key1": "value1",
    "key2": "value2"
}
'''

data['key1']               # <---- TypeError: string indices must be integers

j = json.loads(data)
j['key1']                  # <---- OK

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.

print(type(data))                # <class 'str'>    <---- check the data type

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.

import ast

data = "{'key1': 'value1', 'key2': 'value2'}"

data['key1']                # <---- TypeError: string indices must be integers
j = json.loads(data)        # <---- JSONDecodeError  
j = ast.literal_eval(data)
j['key1']                   # <---- OK

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.

lst = 'my string'
index = input()

lst[index]                                  # <---- TypeError
lst[int(index)]                             # <---- OK

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.

s = 'my string'
s[1,3]                         # <--- TypeError
s[[1,3]]                       # <--- TypeError
s[pd.Series([1,3])]            # <--- TypeError

s[1:3]                         # <--- OK
''.join([s[i] for i in [1,3]]) # <--- OK
无人问我粥可暖 2024-11-16 07:29:41

根据经验,当我在 Python 中收到此错误时,我将函数签名与函数执行进行比较

例如:

def print_files(file_list, parent_id):
    for file in file_list:
        print(title: %s, id: %s' % (file['title'], file['id']

因此,如果我使用以错误顺序放置的参数调用此函数,并将列表作为第二个参数传递,字符串作为第一个参数传递:

print_files(parent_id, list_of_files) # <----- Accidentally switching arguments location

该函数将尝试迭代 parent_id string 而不是 file_list ,并且它期望将索引视为指向字符串中特定字符的整数,而不是字符串索引(titleid)。

这将导致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:

def print_files(file_list, parent_id):
    for file in file_list:
        print(title: %s, id: %s' % (file['title'], file['id']

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:

print_files(parent_id, list_of_files) # <----- Accidentally switching arguments location

The function will try to iterate over the parent_id string instead of file_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 or id).

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.

疏忽 2024-11-16 07:29:41

对我来说,当我尝试获取每个客户端的 id 循环抛出函数 getClientByPoweruser 返回的结果时,我会遇到此错误;
忘记这个函数返回一个带有 successdata 键的对象而不是客户端项目列表,

result = await getClientByPoweruser(poweruser_id, db)
for client in result:
    print(f'client id:{client["id"]}')

这就是我收到错误的原因:

string indices must be integers, not 'str'

要解决这个问题,我只需循环抛出result['data'] 数组,其中真正包含客户端列表:

for client in result['data']: 
    print(f'client id:{client["id"]}')

#results
#client id:1
#client id:2

For me I go this error when I tried to get the id of each clients looping throw the result returned by the function getClientByPoweruser ;
forgetting that this function returns an object with success and data keys rather then list of clients item,

result = await getClientByPoweruser(poweruser_id, db)
for client in result:
    print(f'client id:{client["id"]}')

that is why I got the error:

string indices must be integers, not 'str'

to fix this I had simply to loop throw result['data'] array which really contains the list of clients:

for client in result['data']: 
    print(f'client id:{client["id"]}')

#results
#client id:1
#client id:2
晨曦慕雪 2024-11-16 07:29:41

如果缺少逗号,就会发生这种情况。当我有一个双元组列表时,我遇到了这个问题,每个元组都包含第一个位置的字符串和第二个位置的列表。在一种情况下,我错误地省略了元组的第一个组件后面的逗号,并且解释器认为我正在尝试索引第一个组件。

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.

蘸点软妹酱 2024-11-16 07:29:41

将小写字母转换为大写字母:

str1 = "Hello How are U"

new_str = " "

for i in str1:

        if str1[i].islower():

            new_str = new_str + str1[i].upper()

print(new_str)

错误:

类型错误:字符串索引必须是整数

解决方案:

for i in range(0, len(str1))
// Use range while iterating the string.

Converting the lower case letters to upper:

str1 = "Hello How are U"

new_str = " "

for i in str1:

        if str1[i].islower():

            new_str = new_str + str1[i].upper()

print(new_str)

Error :

TypeError: string indices must be integers

Solution :

for i in range(0, len(str1))
// Use range while iterating the string.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文