0

An example:

y = [1, 0, 0, 1]
y = list(map(lambda i: [0, 1] if i == 1 else [1, 0], y))
print(y)

This runs correctly without error:

[[1, 0], [0, 1], [0, 1], [1, 0]]

However, if I assign the map object to a variable and THEN convert it to a list like this:

y = [1, 0, 0, 1]
y = map(lambda i: [0, 1] if i == 1 else [1, 0], y)
y = list(y)
print(y)

It causes an error:

Traceback (most recent call last):
  File "...\test.py", line 3, in <module>
    y = list(y)
  File "...\test.py", line 2, in <lambda>
    y = map(lambda i: [0, 1] if i == 1 else [1, 0], y)
TypeError: 'map' object is not subscriptable

What is the mechanism behind this? I am confused even though I do have some basic understandings of Python bytecodes and assembly.

Using Python 3.9.7.

Thank you all form stackoverflow! I did not expect such quick help before this post, which is my very first.

I think @Barmar 's detailed answer solves the problem, and @ThierryLathuille 's comment on the question briefly pointed out the core underlying mechanism for me. My sincere gratitude goes for both!

CalmaKarma
  • 61
  • 4
  • Already answered on here: https://stackoverflow.com/questions/6800481/python-map-object-is-not-subscriptable – stefan_aus_hannover Apr 22 '22 at 19:29
  • 1
    `map` returns an iterator, so the lambda doesn't get executed until you pull elements from the iterator, which happens when you build the list. At this point, `y` doesn't refer to the list anymore, but to the `map` object. – Thierry Lathuille Apr 22 '22 at 19:35

2 Answers2

1

You're changing the y variable before the lambda runs.

Try this

y = [1, 0, 0, 1]
m = map(lambda i: [0, 1] if y[i] == 1 else [1, 0], y)
y = list(m)
dirck
  • 838
  • 5
  • 10
  • 1
    BTW I don't think the code or the lambda makes much sense, but that's a separate problem. The lambda should operate on elements of the list, and you're using elements of the list to index the global list (why?). – dirck Apr 22 '22 at 19:35
  • The list contains indexes. – Barmar Apr 22 '22 at 19:39
  • Indexes into what? – dirck Apr 22 '22 at 19:39
  • Into the list itself. – Barmar Apr 22 '22 at 19:40
  • 1
    Yeah, that's what doesn't make sense to me. index 0 into y is 1, index 1 into y is 0. lambda i: 0 if i else 1 (?) – dirck Apr 22 '22 at 19:41
  • It's toy code, probably created to demonstrate this problem. – Barmar Apr 22 '22 at 19:42
  • @dirck It is not quite toy code but me really trying to convert an array of 0's and 1's to an array of one-hot vectors for my MLP code with this when processing the labels. xD – CalmaKarma Apr 22 '22 at 19:58
  • 1
    @CalmaKarma maybe `lambda i: [0, 1] if i==0 else [1, 0]` (?) Sorry, I can't figure it out. – dirck Apr 22 '22 at 20:03
  • @dirck Ah my foolish mistake! Didn't think too much about it. Thanks for pointing out! I will edit my post about this. – CalmaKarma Apr 22 '22 at 20:08
  • That's right! I did not know that map does not execute the function on an element of the iterables until the element is pulled. Thanks a lot! – CalmaKarma Apr 22 '22 at 20:35
1

The problem is that you're using the same variable y for the map as the original list.

In the original code block, you don't reassign y until after list() has iterated over the list. So inside the lambda, y refers to the original list, and you can use y[i] to access those list elements.

But in the version where you assign the result of map() to the variable, y[i] in the lambda is trying to access the map object, not the original list. You get that error because the map object cannot be indexed, only iterated.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Thanks! The answer is really easy to understand combined with @ThierryLathuille 's comment on the question! Thanks again for your immediate comment and answer! – CalmaKarma Apr 22 '22 at 19:51