Neden “TypeError: dize dizinleri tamsayı olmalı” görüyorum?


219

Hem python öğrenmekle hem de github sorunlarını okunabilir bir forma sokmaya çalışıyorum. Tavsiye kullanma Ben CSV JSON dönüştürebilirsiniz nasıl? Ben bununla geldim:

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

Nerede "issue.json" benim github sorunları içeren json dosyasıdır. Bunu çalıştırmaya çalıştığımda,

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

Burada ne eksik? "Dize indeksleri" hangileri? Eminim bu işe başladıktan sonra daha fazla sorunum olacak, ama şimdilik bunun işe yaramasını çok isterim!

İfadeyi forbasitçe

for item in data:
    print item

elde ettiğim şey ... "sorunlar" - bu yüzden daha temel bir yanlış yapıyorum. İşte benim json biraz:

{"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...

Ben yazdırdığımda datagerçekten garip bir şekilde munged gibi görünüyor:

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

Eksik olan print repr(data)ya daimport pprint; pprint.pprint(data)
John Machin

Yanıtlar:


116

itembüyük olasılıkla kodunuzdaki bir dizedir; string indeksleri köşeli parantez içindeki indekslerdir, örn gravatar_id. Bu yüzden ilk önce dataoraya ne aldığınızı görmek için değişkeninizi kontrol ederdim ; Ben tahmin datadizeleri (veya en azından bir dizeyi içeren en az bir listeye) o sözlükler listesi olması gerekirken bir listesidir.


158

Değişken itembir dizedir. Bir dizin şöyle görünür:

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

Yukarıdaki örnek 0, ilk karaktere başvurmak için dizenin dizinini kullanır .

Dizelerde dize indeksleri olamaz (sözlükler gibi). Yani bu işe yaramaz:

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

42

databir dictnesnedir. Yani, bunun gibi tekrarla:

Python 2

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

Python 3

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

36

Dilim Gösterimi için TypeError str[a:b]

tl; dr: bir kullanımı kolon : yerine bir virgül iki endeks arasında ave biçindestr[a:b]


Çalışırken dizeleri ve dilim gösterimde (bir ortak dizi operasyon ), bir o olabilir TypeErrorAçıkçası olsalar bile endeksleri tamsayı olması gerektiğini işaret ederek, yükseltilir.

Misal

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

Endeksler için iki tamsayıyı dilim gösterimine geçirmiştik, değil mi? Peki burada sorun ne?

Bu hata - özellikle Python öğrenmenin başlangıcında - çok sinir bozucu olabilir, çünkü hata mesajı biraz yanıltıcıdır.

açıklama

Aradığımızda dilim göstergesine örtülü olarak iki tamsayı (0 ve 5) geçtik my_string[0,5]çünkü 0,5(parantez olmadan bile) yaptığı gibi aynı tupa değerlendiriyor (0,5).

,Python'un bir şeyi bir demet olarak değerlendirmesi için virgül yeterlidir:

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

Peki orada ne yaptık, bu sefer açıkça:

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

Şimdi, en azından, hata mesajı mantıklı.

Çözüm

Biz değiştirmeniz gerekiyor virgül , bir ile kolon : doğru iki tamsayı ayırmak için:

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

Daha net ve daha yararlı bir hata mesajı şöyle olabilir:

TypeError: string indices must be integers (not tuple)

İyi bir hata mesajı kullanıcıya neyi yanlış yaptığını doğrudan gösterir ve sorunun nasıl çözüleceği daha açık olurdu.

[Bir dahaki sefere bir hata açıklama mesajı yazmaktan kendinizi sorumlu bulduğunuzda, bu örneği düşünün ve hata mesajına nedeni veya diğer yararlı bilgileri, belki de başkalarının neyin yanlış gittiğini anlamalarına izin vermek için hata mesajına ekleyin.]

Dersler öğrenildi

  • dilim gösterimi :, indekslerini ayırmak için iki nokta üst üste kullanır (ve adım aralığı, ör. str[from:to:step])
  • tuples virgülle tanımlanır ,(ör. t = 1,)
  • kullanıcıların neyin yanlış gittiğini anlaması için hata mesajlarına biraz bilgi ekleyin

Şerefe ve mutlu programlama
winklerrr


[Bu sorunun zaten cevaplandığını biliyorum ve bu tam olarak iplik başlatıcısının sorduğu soru değildi, ama aynı hata mesajına yol açan yukarıdaki sorun nedeniyle buraya geldim. En azından o küçük yazım hatasını bulmak biraz zamanımı aldı.

Bu yüzden bunun aynı hatayı tökezleyen birisine yardımcı olacağını ve onlara bu küçük hatayı bulmalarında zaman kazandıracağını umuyorum.]


0

Virgül eksikse bu olabilir. Her biri ilk pozisyonda bir dize ve ikincisinde bir listeden oluşan iki tuple içeren bir listem olduğunda karşılaştım. Bir durumda bir demetin ilk bileşeninden sonra virgül yanlışlıkla atladım ve yorumlayıcı ilk bileşeni dizine eklemeye çalıştığımı düşündü.


0

Pandalar ile benzer bir sorunum vardı, iterrows için bir Pandas veri kümesi Pandas belgelerini tekrarlamak için iterrows () işlevini kullanmanız gerekir

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

işlev tarafından da döndürülen veri kümesindeki dizini işlemeniz gerektiğini unutmayın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.