Waarom zie ik “TypeError: string indices must be integers”?

Ik speel met zowel het leren van python als het proberen om github-problemen in een leesbare vorm te krijgen. Met behulp van het advies op Hoe kan ik JSON naar CSV converteren? kwam ik met dit:

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","votes","created_at","comments","body","title","updated_at","html_url","user","labels","state"])
for item in data:
        csv_file.writerow([item["gravatar_id"], item["position"], item["number"], item["votes"], item["created_at"], item["comments"], item["body"], item["title"], item["updated_at"], item["html_url"], item["user"], item["labels"], item["state"]])

Waarbij “issues.json” het json-bestand is dat mijn github-problemen bevat. Als ik dat probeer uit te voeren, krijg ik

File "foo.py", line 14, in <module>
csv_file.writerow([item["gravatar_id"], item["position"], item["number"], item["votes"], item["created_at"], item["comments"], item["body"], item["title"], item["updated_at"], item["html_url"], item["user"], item["labels"], item["state"]])
TypeError: string indices must be integers

Wat mis ik hier? Wat zijn de “stringindexen”? Ik weet zeker dat als ik dit eenmaal werkend heb, ik meer problemen zal hebben, maar voor nu zou ik graag willen dat dit werkt!

Als ik de for-instructie aanpas om eenvoudig

for item in data:
    print item

wat ik krijg is … “problemen” — dus ik doe iets fundamentelers verkeerd. Hier is een beetje van mijn json:

{"issues":[{"gravatar_id":"44230311a3dcd684b6c5f81bf2ec9f60","position":2.0,"number":263,"votes":0,"created_at":"2010/09/17 16:06:50 -0700","comments":11,"body":"Add missing paging (Older>>) links...

wanneer ik data afdruk, lijkt het alsof het heel vreemd wordt vermengd:

{u'issues': [{u'body': u'Add missing paging (Older>>) lin...

Antwoord 1, autoriteit 100%

item is hoogstwaarschijnlijk een tekenreeks in uw code; de tekenreeksindexen zijn die tussen vierkante haken, bijvoorbeeld gravatar_id. Dus ik zou eerst je variabele data controleren om te zien wat je daar hebt ontvangen; Ik denk dat data een lijst met strings is (of op zijn minst een lijst met minstens één string), terwijl het een lijst met woordenboeken zou moeten zijn.


Antwoord 2, autoriteit 126%

De variabele item is een string. Een index ziet er als volgt uit:

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

In het bovenstaande voorbeeld wordt de index 0 van de tekenreeks gebruikt om naar het eerste teken te verwijzen.

Tekenreeksen kunnen geen tekenreeksindexen hebben (zoals woordenboeken dat wel kunnen). Dit werkt dus niet:

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

Antwoord 3, autoriteit 40%

TypeError voor segmentnotatie str[a:b]


Kort antwoord

Gebruik een dubbele punt : in plaats van een komma tussen de twee indices a en b in str[a:b] (bijv. in plaats van my_string[0,5] schrijf my_string[0:5]) .


Lang antwoord

Bij het werken met strings en slice-notatie (een common sequence-bewerking), kan het gebeuren dat een TypeError wordt gegenereerd, wat erop wijst dat de indices gehele getallen moeten zijn, zelfs als ze dat duidelijk zijn .

Voorbeeld

>>> my_string = "hello world"
>>> my_string[0,5]
TypeError: string indices must be integers

We hebben duidelijk twee gehele getallen voor de indices doorgegeven aan de slice-notatie, toch? Dus wat is hier het probleem?

Deze fout kan erg frustrerend zijn – vooral aan het begin van het leren van Python – omdat de foutmelding een beetje misleidend is.

Uitleg

We hebben impliciet een tupel van twee gehele getallen (0 en 5) doorgegeven aan de plaknotatie toen we my_string[0,5] aanriepen omdat 0,5 (zelfs zonder de haakjes) evalueert tot hetzelfde tuple als (0,5) zou doen.

Een komma , is eigenlijk genoeg voor Python om iets als een tuple te evalueren:

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

Dus wat we daar deden, deze keer expliciet:

>>> my_string = "hello world"
>>> my_tuple = 0, 5
>>> my_string[my_tuple]
TypeError: string indices must be integers

Nu is de foutmelding tenminste logisch.

Oplossing

We moeten de komma , vervangen door een dubbele punt : om de twee gehele getallen correct te scheiden:

>>> my_string = "hello world"
>>> my_string[0:5]
'hello'

Een duidelijkere en nuttigere foutmelding had zoiets kunnen zijn als:

TypeError: string indices must be integers (not tuple)

Een goede foutmelding laat de gebruiker direct zien wat hij verkeerd heeft gedaan en het zou duidelijker zijn geweest hoe het probleem kon worden opgelost.

[Dus de volgende keer dat u merkt dat u verantwoordelijk bent voor het schrijven van een foutbeschrijvingsbericht, denk dan aan dit voorbeeld en voeg de reden of andere nuttige informatie toe aan het foutbericht zodat u en misschien andere mensen begrijpen wat er fout is gegaan.]

Leren geleerd

  • slice-notatie gebruikt dubbele punten : om de indices (en stapbereik, bijv. str[from:to:step]) te scheiden
  • tupels worden gedefinieerd door komma’s , (bijv. t = 1,)
  • wat informatie aan foutmeldingen toevoegen zodat gebruikers begrijpen wat er mis is gegaan

Proficiat en veel plezier met programmeren
winklerrr


[Ik weet dat deze vraag al is beantwoord en dit was niet precies de vraag die de topicstarter stelde, maar ik kwam hier vanwege het bovenstaande probleem dat tot dezelfde foutmelding leidt. Het kostte me in ieder geval behoorlijk wat tijd om die kleine typfout te vinden.

Dus ik hoop dat dit iemand anders zal helpen die op dezelfde fout is gestuit en dat het hem wat tijd bespaart om die kleine fout te vinden.]


Antwoord 4, autoriteit 37%

data is een dict object. Herhaal het dus als volgt:

Python 2

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

Python 3

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

Antwoord 5, autoriteit 2%

Ik had een soortgelijk probleem met Panda’s, je moet de functie iterrows() gebruiken om een ​​Pandas-dataset te doorlopen Pandas-documentatie voor iterrows

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

merk op dat u de index in de dataset moet behandelen die ook door de functie wordt geretourneerd.


Antwoord 6

Dit kan gebeuren als er een komma ontbreekt. Ik kwam het tegen toen ik een lijst met twee-tupels had, die elk bestonden uit een string op de eerste positie en een lijst op de tweede. In één geval heb ik ten onrechte de komma na de eerste component van een tupel weggelaten, en de interpreter dacht dat ik de eerste component probeerde te indexeren.


Antwoord 7

Als vuistregel, wanneer ik deze fout ontvang in Python, vergelijk ik de functiehandtekening met de functie-uitvoering.

Bijvoorbeeld:

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

Dus als ik deze functie aanroep met parameters in de verkeerde volgorde geplaatst en de lijst doorgeef als het 2e argument en een string als het 1e argument:

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

De functie zal proberen de parent_id string te herhalen in plaats van file_list en zal de index verwachten als een geheel getal dat verwijst naar het specifieke teken in de string en niet een index die een tekenreeks is (title of id).

Dit leidt tot de fout TypeError: string indices must be integers.

Vanwege zijn dynamische aard (in tegenstelling tot talen als Java, C# of Typescript), zal Python u niet informeren over deze syntaxisfout.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

two × one =

Other episodes