-1

I've been searching around for a succinct explanation of what's going on "under the hood" for the following, but no luck so far.

Why, when you try the following:

mylist = ["a","b","c","d"]

for index, item in mylist:
    print item

I get this error:

ValueError: need more than 1 value to unpack

But when I try:

for item in mylist:
    print item

This is returned:

a
b
c
d

If indexes are a part of the structure of a list, why can't I print them out along with the items?

I understand the solution to this is to use enumerate(), but I'm curious about why iterating through lists (without using enumerate()) works this way and returns that ValueError.

I think what I'm not understanding is: if you can find items in a list by using their index (such as the case with item = L[index] ) — doesn't that mean that one some level, indexes are an inherent part of a list as a data structure? Or is item = L[index] really just a way to get Python to count the items in a list using indexes (starting at 0 obviously)? In other words, item = L[index] is "applying" indexes to the items in the list, starting at 0.

AdjunctProfessorFalcon
  • 1,790
  • 6
  • 26
  • 62
  • 1
    `enumerate` returns a generator of `tuple` of the form `(index, value)`. So you are unpacking each tuple. When you try to unpack `mylist`, there is no index, it thinks you are trying to unpack each element of the list into your two variables `index` and `item`. Since each item is a string of length 1, it is complaining that you cannot unpack one character into two variables – Cory Kramer Jun 09 '15 at 20:00
  • 1
    if that worked why would you need enumerate? – Padraic Cunningham Jun 09 '15 at 20:02
  • @Malvin9000, the OP is asking why does my code not do the same thing that happens when I use enumerate when I don't which would mean if it did you would not need enumerate which makes little sense – Padraic Cunningham Jun 09 '15 at 20:05
  • @GillBates, yes you basically are asking that, why would enumerate exist if you could do what you are trying to do? Where in any documentation does it say *indexes are a part of the structure of a list*? – Padraic Cunningham Jun 09 '15 at 20:10

2 Answers2

3

If indexes are a part of the structure of a list...

Except they aren't. Not when you iterate over the list. The indexing becomes a matter of time/occurrence, and they are no longer associated with the elements themselves.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • So we can find items in a list by index using something like `item = L[index]` but when you iterate through a list (without using enumerate), there are no indexes associated with the list? – AdjunctProfessorFalcon Jun 09 '15 at 20:12
  • 1
    Correct, because you can't even assume that you're iterating over a list in the first place. It can be *any* iterable, including ones where the concept of "index" is utterly meaningless such as a dict or generator. – Ignacio Vazquez-Abrams Jun 09 '15 at 20:16
  • @GillBates Regardless of whether or not the index is part of the internal list structure, the list iterator does not provide it; it only provides the list elements. – Colonel Thirty Two Jun 09 '15 at 20:26
  • @ColonelThirtyTwo Sorry, I'm not clear on what you mean by "the list iterator" in this case. – AdjunctProfessorFalcon Jun 09 '15 at 20:29
1

If you were to actually print out the result of the enumerate() function as a list:

print(list(enumerate(["a","b","c","d"])))

You would see this:

[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

Therefore, if you wanted to print the index and item at that index using enumerate(), you could technically write this:

for pair in enumerate(mylist):
    print pair[0], pair[1]

However, that's not the best (i.e. Pythonic) way of doing things. Python lets you write the above much more nicely like so:

for index, item in enumerate(mylist):
    print index, item

This works because when you use the index, item syntax, you are telling Python to "unpack" each pair in that list by treating the components of each pair separately.

For more on how this tuple unpacking magic works, see: Tuple unpacking in for loops

Community
  • 1
  • 1
caleb531
  • 4,111
  • 6
  • 31
  • 41
  • @caelb531 Thanks for the above, I understand how enumerate works. My question is that, when you read about lists and people are saying that all lists start at index[0], that says to me that somehow indexes are "built into" the structure of a list. So that's why I'm not understanding why you're not able to iterate over indexes and items together in a list without using enumerate. – AdjunctProfessorFalcon Jun 09 '15 at 20:19
  • 1
    @GillBates Don't let the subscript notation (`[0]`) deceive you. Just because you need an index to retrieve an item from the list doesn't mean that index is actually stored on the list. The indices aren't actually stored on the list objects themselves; that would be horribly inefficient. Instead, Python stores list items in such a way that it knows which item to retrieve given some index. Many other programming languages work similarly. – caleb531 Jun 09 '15 at 20:31
  • @caelb531 Ok, so just to be clear: the final answer is, list objects do not have indexes built into them, correct? And `item = L[index]` is really just a way to get Python to count the items in a list using indexes (starting at 0 obviously)? In other words, `item = L[index]` is "applying" indexes to the items in the list, starting at 0. – AdjunctProfessorFalcon Jun 09 '15 at 21:50
  • Yes, that's true for both lists and tuples (which are just immutable lists). :) – caleb531 Jun 09 '15 at 22:04