Python-Map-Objekt ist nicht abonnierbar

81

Warum gibt das folgende Skript den Fehler aus:

payIntList[i] = payIntList[i] + 1000
TypeError: 'map' object is not subscriptable

payList = []
numElements = 0

while True:
        payValue = raw_input("Enter the pay amount: ")
        numElements = numElements + 1
        payList.append(payValue)
        choice = raw_input("Do you wish to continue(y/n)?")
        if choice == 'n' or choice == 'N':
                         break

payIntList = map(int,payList)

for i in range(numElements):
         payIntList[i] = payIntList[i] + 1000
         print payIntList[i]
Bahnhof
quelle
5
Verwenden Sie Python 3?
Felix Kling
@ user567797 - Das funktioniert gut für mich @ Felix: Er verwendet Python 3 nicht, da er Print als Anweisung verwendet!
Pushpak Dagade
2
Das Ganze unterhalb der while-Schleife kann auf payIntList = [int(x) + 1000 for x in payList]; print(*payIntList, sep='\n')(oder for x in payIntList: print xin Python 2.x, wo printes keine Funktion gibt) gekürzt werden, ohne die Lesbarkeit zu verlieren (wahrscheinlich ist es sogar noch besser lesbar).
2
@Guanidene: Er verwendet Python 3, da er Kartenobjekte hat. Aber er versucht, Python 2-Code darauf auszuführen, daher die Fehler.
Lennart Regebro
3
Ich hätte gerne die Frage "Warum erhalte ich Fehler, wenn ich Python 2-Code auf Python 3 ausführe?", Die wir alle als Duplikate markieren können. ;)
Lennart Regebro

Antworten:

136

mapGibt in Python 3 ein iterierbares Objekt vom Typ mapund keine abonnierbare Liste zurück, mit der Sie schreiben können map[i]. Schreiben Sie, um ein Listenergebnis zu erzwingen

payIntList = list(map(int,payList))

In vielen Fällen können Sie Ihren Code jedoch viel besser ausschreiben, indem Sie keine Indizes verwenden. Zum Beispiel mit Listenverständnis :

payIntList = [pi + 1000 for pi in payList]
for pi in payIntList:
    print(pi)
Phihag
quelle
6
Diese Antwort ist richtig, aber im Idealfall würden Sie keine Karten für solche Anwendungsfälle in Listen konvertieren. Karten sind bereits iterierbar und scheinen im Vergleich zu Listen eine Größenordnung schneller zu durchlaufen zu sein. Sie brauchen also nicht nur keinen Index, sondern überhaupt keine Liste. Der sauberere Code wäre, da payIntList bereits eine Karte ist,for i in payIntList: print(i + 1000)
RustyToms
17

map()Gibt keine Liste zurück, sondern ein mapObjekt.

Sie müssen anrufen, list(map)wenn Sie möchten, dass es wieder eine Liste ist.

Noch besser,

from itertools import imap
payIntList = list(imap(int, payList))

Nimmt nicht viel Speicherplatz in Anspruch, um ein Zwischenobjekt zu erstellen, sondern gibt es nur intsaus, wenn es erstellt wird.

Sie können dies auch tun, if choice.lower() == 'n':damit Sie es nicht zweimal tun müssen.

Python unterstützt +=: Sie können payIntList[i] += 1000und numElements += 1wenn Sie wollen.

Wenn Sie wirklich knifflig sein wollen:

from itertools import count
for numElements in count(1):
    payList.append(raw_input("Enter the pay amount: "))
    if raw_input("Do you wish to continue(y/n)?").lower() == 'n':
         break

und / oder

for payInt in payIntList:
    payInt += 1000
    print payInt

Außerdem sind vier Leerzeichen der Standard-Einrückungsbetrag in Python.

agf
quelle
1
Nun, das ist bei python3 der Fall, aber hier scheint er python2.x zu verwenden, da er print als Anweisung verwendet.
Pushpak Dagade
Ihr Code - Snippet tut speichert alle ints im Speicher in einer Liste. Die Verwendung von Iteratoren ist in der Tat nützlich und spart Speicher, insbesondere bei mehreren Transformationsebenen. Das Hinzufügen listeines Iterators nimmt diesen Vorteil jedoch weg!
1
Wenn Sie dies tun list(map(...)), wird ein erstellt map, dann ein erstellt listund dann das gelöscht map, sodass beide für eine Weile gleichzeitig im Speicher sind. Wenn Sie dies tun, ist list(imap(...))dies nicht der Fall. Deshalb habe ich gesagt "Nehmen Sie Speicher mit einem Zwischenobjekt auf "
agf
Sie nehmen also Python 2 an? Dann list(map(...))ist redundant, weil - wie in der Dokumentation angegeben , "das Ergebnis [von map] immer eine Liste ist".