El objeto de mapa de Python no se puede suscribir

82

¿Por qué el siguiente script da el error?

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]
estación
fuente
5
¿Estás usando Python 3?
Felix Kling
@ user567797 - Esto funciona bien para mí @ Felix: ¡No está usando Python 3 ya que usa print como una declaración!
Pushpak Dagade
2
Todo lo que está debajo del bucle while se puede acortar a payIntList = [int(x) + 1000 for x in payList]; print(*payIntList, sep='\n')(o for x in payIntList: print xen Python 2.x donde printno es una función) sin perder legibilidad (posiblemente, es aún más legible).
2
@Guanidene: Está usando Python 3, ya que tiene objetos de mapa. Pero está intentando ejecutar código Python 2 en él, de ahí los errores.
Lennart Regebro
3
Me gustaría una pregunta "¿Por qué obtengo errores cuando ejecuto el código Python 2 en Python 3?", Que podamos marcar todos como duplicados. ;)
Lennart Regebro

Respuestas:

136

En Python 3, mapdevuelve un objeto iterable de tipo map, y no una lista subcriptible, lo que le permitiría escribir map[i]. Para forzar un resultado de lista, escriba

payIntList = list(map(int,payList))

Sin embargo, en muchos casos, puede escribir su código de una manera más agradable si no usa índices. Por ejemplo, con listas por comprensión :

payIntList = [pi + 1000 for pi in payList]
for pi in payIntList:
    print(pi)
Phihag
fuente
6
Esta respuesta es correcta, pero lo ideal es que no convierta mapas en listas para casos de uso como este. Los mapas ya son iterables y parecen ser un orden de magnitud más rápido de recorrer en comparación con las listas. Entonces, no solo no necesita un índice, no necesita una lista en absoluto. El código más limpio sería, dado que payIntList ya es un mapa,for i in payIntList: print(i + 1000)
RustyToms
17

map()no devuelve una lista, devuelve un mapobjeto.

Debes llamar list(map)si quieres que vuelva a ser una lista.

Aun mejor,

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

No ocupará un montón de memoria creando un objeto intermedio, simplemente lo pasará intsa medida que lo crea.

Además, puede hacerlo if choice.lower() == 'n':para no tener que hacerlo dos veces.

Soportes de Python +=: puedes hacerlo payIntList[i] += 1000y numElements += 1si quieres.

Si realmente quieres ser complicado:

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

y / o

for payInt in payIntList:
    payInt += 1000
    print payInt

Además, cuatro espacios es la cantidad de sangría estándar en Python.

agf
fuente
1
Bueno, ese es el caso de python3, pero aquí parece estar usando python2.x ya que usa print como una declaración.
Pushpak Dagade
El fragmento de código hace almacenar todos los enteros en la memoria en una lista. El uso de iteradores es realmente útil y ahorra memoria, especialmente con múltiples capas de transformaciones, ¡pero agregar listalrededor de un iterador elimina esa ventaja!
1
Cuando lo haces list(map(...)), crea un map, luego crea un list, luego borra el map, por lo que durante un tiempo ambos están en la memoria a la vez. Cuando lo haces, list(imap(...))este no es el caso. Por eso dije "tomar memoria con un objeto intermedio "
agf
¿Entonces estás asumiendo Python 2? Entonces list(map(...))es redundante, porque - como dice la documentación , "el resultado [de map] es siempre una lista".