105

Why does the following script give the 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]
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
station
  • 6,715
  • 14
  • 55
  • 89
  • 8
    Are you using Python 3 ? – Felix Kling Jul 23 '11 at 12:55
  • @user567797 - This works fine for me @ Felix: He is not using python 3 as he is using print as a statement! – Pushpak Dagade Jul 23 '11 at 12:58
  • 2
    The whole thing below the while loop can be shortened to `payIntList = [int(x) + 1000 for x in payList]; print(*payIntList, sep='\n')` (or `for x in payIntList: print x` in Python 2.x where `print` isn't a function) without losing readability (arguably, it's even more readable). –  Jul 23 '11 at 12:59
  • 2
    @Guanidene: He is using Python 3, as he has map objects. But he is trying to run Python 2 code on it, hence the errors. – Lennart Regebro Nov 17 '11 at 14:58
  • 3
    I'd like a "Why do I get errors when I run Python 2 code on Python 3" question, that we can mark all of these as duplicates to. ;) – Lennart Regebro Nov 17 '11 at 14:58

3 Answers3

178

In Python 3, map returns an iterable object of type map, and not a subscriptible list, which would allow you to write map[i]. To force a list result, write

payIntList = list(map(int,payList))

However, in many cases, you can write out your code way nicer by not using indices. For example, with list comprehensions:

payIntList = [pi + 1000 for pi in payList]
for pi in payIntList:
    print(pi)
phihag
  • 278,196
  • 72
  • 453
  • 469
  • 9
    This answer is correct, but ideally you would not be converting maps to lists for use cases such as this. Maps are already iterable, and appear to be an order of magnitude faster to iterate through compared to lists. So not only do you not need an index, you don't need a list at all. The cleaner code would be, since payIntList is already a map, `for i in payIntList: print(i + 1000)` – RustyToms Aug 17 '18 at 03:39
23

map() doesn't return a list, it returns a map object.

You need to call list(map) if you want it to be a list again.

Even better,

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

Won't take up a bunch of memory creating an intermediate object, it will just pass the ints out as it creates them.

Also, you can do if choice.lower() == 'n': so you don't have to do it twice.

Python supports +=: you can do payIntList[i] += 1000 and numElements += 1 if you want.

If you really want to be tricky:

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

and / or

for payInt in payIntList:
    payInt += 1000
    print payInt

Also, four spaces is the standard indent amount in Python.

agf
  • 171,228
  • 44
  • 289
  • 238
  • 1
    Well that is the case for python3, but here he seems to be using python2.x as he is using print as a statement. – Pushpak Dagade Jul 23 '11 at 13:00
  • Your code snippet *does* store all ints in memory in a list. Using iterators is indeed useful and saves memory, especially with multiple layers of transformations, but adding `list` around an iterator takes away that advantage! –  Jul 23 '11 at 13:02
  • 1
    When you do `list(map(...))` it creates a `map`, then creates a `list`, then deletes the `map`, so for a while both are in memory at once. When you do `list(imap(...))` this isn't the case. That's why I said "take up memory with an _intermediate_ object" – agf Jul 23 '11 at 13:04
  • So you are assuming Python 2? Then `list(map(...))` is redundant, because - as the [documentation](http://docs.python.org/library/functions.html#map) states, "the result [of `map`] is always a list". –  Jul 23 '11 at 14:16
0

Don't need to use range for this problem in pypy3 or python3, so it is actually less code..

for i in payIntList: print ( i + 1000 )

and coincidentally matches RustyTom's comment in PhiHag's solution above. Note : Can not reference a map using array brackets [] in pypy3 or python3 or it will throw the same error.

payIntList[i] 

Map ref caused the error.

Joseph Poirier
  • 386
  • 2
  • 17