Об’єкт карти Python не підписується


83

Чому такий сценарій видає помилку:

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]

5
Ви використовуєте Python 3?
Фелікс Клінг,

@ user567797 - Для мене це чудово працює @ Felix: Він не використовує python 3, оскільки використовує print як заяву!
Pushgade Dagade

2
Усе, що знаходиться під циклом while, можна скоротити до payIntList = [int(x) + 1000 for x in payList]; print(*payIntList, sep='\n')(або for x in payIntList: print xв Python 2.x, де printце не є функцією), не втрачаючи читабельності (можливо, це ще більше читається).

2
@Guanidene: Він використовує Python 3, оскільки має об’єкти карти. Але він намагається запустити на ньому код Python 2, звідси і помилки.
Леннарт Регебро

3
Я хотів би поставити запитання "Чому я отримую помилки під час запуску коду Python 2 на Python 3", щоб ми могли позначити їх усі як дублікати. ;)
Леннарт Регебро

Відповіді:


138

У Python 3 mapповертає об'єкт типу map, який можна повторити , а не список, що підписується , що дозволить вам писати map[i]. Щоб примусити результат списку, напишіть

payIntList = list(map(int,payList))

Однак у багатьох випадках ви можете виписати свій код набагато краще, не використовуючи індекси. Наприклад, із розумінням списку :

payIntList = [pi + 1000 for pi in payList]
for pi in payIntList:
    print(pi)

6
Ця відповідь правильна, але в ідеалі ви не перетворювали б карти у списки для таких випадків використання, як цей. Карти вже можна повторити, і, здається, на порядок швидше їх переглядати в порівнянні зі списками. Тож вам не тільки не потрібен індекс, а й зовсім не потрібен список. Чистішим був би код, оскільки payIntList - це вже карта,for i in payIntList: print(i + 1000)
RustyToms

17

map()не повертає список, він повертає mapоб'єкт.

Вам потрібно зателефонувати, list(map)якщо ви хочете, щоб це знову був список.

Навіть краще,

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

Не буде займати купу пам'яті, створюючи проміжний об'єкт, він просто передаватиме ints, коли створює їх.

Крім того, ви можете зробити if choice.lower() == 'n':це, і вам не потрібно робити це двічі.

Python підтримує +=: ви можете зробити payIntList[i] += 1000і numElements += 1якщо ви хочете.

Якщо ви дійсно хочете бути хитрим:

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

та / або

for payInt in payIntList:
    payInt += 1000
    print payInt

Крім того, чотири пробіли - це стандартний відступ у Python.


1
Ну, це стосується python3, але тут він, схоже, використовує python2.x, оскільки використовує print як оператор.
Pushgade Dagade

Ваш фрагмент коду робить зберігати все Інтс в пам'яті в списку. Використання ітераторів дійсно корисно і економить пам’ять, особливо при декількох шарах перетворень, але додавання listнавколо ітератора забирає цю перевагу!

1
Коли ви list(map(...))це робите, він створює a map, потім створює a list, а потім видаляє map, так що деякий час обидва вони залишаються в пам'яті одночасно. Коли ви робите list(imap(...))це не так. Тому я сказав "займати пам'ять проміжним об'єктом"
agf

Отже, ви припускаєте Python 2? Тоді list(map(...))є зайвим, оскільки - як зазначено в документації , "результат [of map] - це завжди список".
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.