¿Por qué veo "TypeError: los índices de cadenas deben ser números enteros"?

Resuelto Amanda asked hace 13 años • 10 respuestas

Estoy jugando con el aprendizaje de Python y estoy tratando de convertir los problemas de GitHub en un formato legible. Siguiendo los consejos sobre ¿Cómo puedo convertir JSON a CSV? , se me ocurrió esto:

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"]])

Donde "issues.json" es el archivo JSON que contiene mis problemas de GitHub. Cuando intento ejecutar eso, me sale

TypeError: string indices must be integers

¿Que me estoy perdiendo aqui? ¿Cuáles son los "índices de cadena"?

Aquí hay un poco de mi contenido JSON:

{"issues": [{"gravatar_id": "44230311a3dcd684b6c5f81bf2ec9f60", "position": 2.0, "number": 263...
Amanda avatar May 21 '11 04:05 Amanda
Aceptado

La variable itemes una cadena. Un índice se parece a esto:

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

El ejemplo anterior utiliza el 0índice de la cadena para referirse al primer carácter.

Las cadenas no pueden tener índices de cadena (como los diccionarios). Entonces esto no funcionará:

>>> mystring = 'helloworld'
>>> print mystring['stringindex']
TypeError: string indices must be integers
bluepnume avatar May 20 '2011 21:05 bluepnume

itemLo más probable es que sea una cadena en su código; los índices de cadena son los que están entre corchetes, por ejemplo, gravatar_id. Así que primero verificaría tu datavariable para ver qué recibiste allí; Supongo que dataes una lista de cadenas (o al menos una lista que contiene al menos una cadena), mientras que debería ser una lista de diccionarios.

Tamás avatar May 20 '2011 21:05 Tamás

Error de tipo para notación de sectoresstr[a:b]


Respuesta corta

Utilice dos puntos : en lugar de una coma , entre los dos índices ay ben str[a:b]:

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

Respuesta larga

Cuando se trabaja con cadenas y notación de corte (una operación de secuencia común ), puede suceder que TypeErrorse eleve a, señalando que los índices deben ser números enteros, incluso si obviamente lo son.

Ejemplo

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

Obviamente pasamos dos números enteros para los índices de la notación de corte, ¿verdad? Entonces, ¿cuál es el problema aquí?

Este error puede ser muy frustrante, especialmente al comienzo del aprendizaje de Python, porque el mensaje de error es un poco engañoso.

Explicación

Implícitamente pasamos tupledos enteros a la notación de segmento cuando llamamos my_string[0,5]. 0,5se evalúa como la misma tupla que (0,5)lo hace, incluso sin los paréntesis. ¿Por qué sin embargo?

En realidad , una coma final ,es suficiente para que el intérprete de Python evalúe algo como una tupla:

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

Entonces, lo que hicimos allí, esta vez explícitamente:

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

Ahora, al menos, el mensaje de error tiene sentido.

Solución

Necesitamos reemplazar la coma , con dos puntos : para separar los dos números enteros correctamente, sin que se interpreten como tuple:

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

Un mensaje de error más claro y útil podría haber sido algo como:

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

¡Un buen mensaje de error debería mostrarle al usuario directamente qué hizo mal! Con este tipo de información habría sido mucho más fácil encontrar la causa raíz y resolver el problema, y ​​no habría tenido que venir aquí.

Entonces, la próxima vez, cuando sea responsable de escribir mensajes de descripción de error, recuerde este ejemplo y agregue el motivo (u otra información útil) al mensaje de error. Ayude a otras personas (o tal vez incluso a su yo futuro) a comprender qué salió mal.

Lecciones aprendidas

  • la notación de corte utiliza dos puntos :para separar sus índices (y rango de pasos, es decir, str[from:to:step])
  • las tuplas se definen mediante comas ,(es decir, t = 1,)
  • agregue información a los mensajes de error para que los usuarios comprendan qué salió mal
winklerrr avatar Aug 30 '2018 13:08 winklerrr

dataes un dictobjeto. Entonces, repítelo de esta manera:

Pitón 2

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

Pitón 3

for key, value in data.items():
    print(key, value)
John Machin avatar May 20 '2011 23:05 John Machin

Tuve un problema similar con Pandas, necesitas usar la función iterrows() para iterar a través de un conjunto de datos de Pandas Documentación de Pandas para iterrows

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

tenga en cuenta que debe manejar el índice en el conjunto de datos que también devuelve la función.

coremonkey avatar Nov 28 '2019 08:11 coremonkey