# Python For Loops Do Not Behave As Expected

**URL:** <https://discuss.python.org/t/python-for-loops-do-not-behave-as-expected/8279>\
**Category:** Python Help\
**Created:** [April 18, 2021, 5:08am UTC](https://discuss.python.org/t/python-for-loops-do-not-behave-as-expected/8279 "2021-04-18T05:08:07Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Samuel](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/samuel/32/3209_2.png) [@Samuel](https://discuss.python.org/u/Samuel)\
**Post date:** [April 18, 2021, 5:08am UTC](https://discuss.python.org/t/python-for-loops-do-not-behave-as-expected/8279/1 "2021-04-18T05:08:07Z")

</div>

For loops in Python are baffling to a VBA programmer.

```auto
NumLst = [8, 1, 3, 2]
for I in NumLst:
    print (I, end = ' ')

```

Output from this is  
8 1 3 2

Not what I expected. I thought was asking Python to print the loop counter, not the contents of the loop.  
I expected 0 1 2 3

Thought maybe `enumerate’ would get the result I expected. And it does - Kind of.

```auto
NumLst = [8, 1, 3, 2]
for I in enumerate (NumLst):
    print (I)

```

This code gives us  
(0, 8)  
(1, 1)  
(2, 3)  
(3, 2)

So it does print the loop counter, even if still not what I had in mind.

But all of the above is immaterial. I got sidetracked on trying to grasp for loops because I was unable to do what I originally set out to do. I wanted  
to replace one or more of the values in NumLst with a different value. Tried this code:

```auto
for I in enumerate (NumLst):
    NumLst [I] = NumLst [I] + 1
    print (I)
print (NumLst)    

```

I expected  
9  
2  
4  
3

Instead I got:  
Traceback (most recent call last):  
File “C:/Users/Sam/AppData/Local/Programs/Python/Python39/Python OutPut/Prac 02.Py”, line 50, in   
NumLst [I] = NumLst [I] + 1  
TypeError: list indices must be integers or slices, not tuple

Well, the list indices ARE integers. Aren’t they??

So once more I’m asking you guys to point me in the right direction.

---

<div class="post-metadata">

**Author:** ![jeanas](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jeanas/32/8115_2.png) [@jeanas](https://discuss.python.org/u/jeanas)\
**Post date:** [April 18, 2021, 6:18am UTC](https://discuss.python.org/t/python-for-loops-do-not-behave-as-expected/8279/2 "2021-04-18T06:18:01Z")

</div>

`for value in some_list` lets `value` iterate over all the elements of the list, not the possible indices for the list. Think `for cake in all_pancakes: eat(cake)`. Indeed, this is different from the idioms found in other languages. In Python, the for loop works with an _iterator_, which yields the values. Lists are iterators, yielding their own values.

If you want an index, use `range()` (which yields integers):

```auto
for i in range(len(NumLst)):
    NumLst[i] += 1

```

The `enumerate` function is a convenient way to iterate over the indices and values at the same time. When you write `for thing in enumerate(NumLst):`, then at every step, `thing` is a 2-tuple containing an index and a value. It is not valid to pass this as an index to a list. You want to deconstruct it, which is most convenient in the line of the `for`:

```auto
for i, value in enumerate(NumLst):
    NumLst[i] = value + 1

```

---

<div class="post-metadata">

**Author:** ![steven.daprano](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steven.daprano/32/1083_2.png) [@steven.daprano](https://discuss.python.org/u/steven.daprano)\
**Post date:** [April 18, 2021, 6:51am UTC](https://discuss.python.org/t/python-for-loops-do-not-behave-as-expected/8279/3 "2021-04-18T06:51:51Z")

</div>

There is no “loop counter” in Python, unless you specifically ask for  
one. The usual way to do that is with enumerate.

```
for i, x in enumerate('abc'):
    print(i, x, end=' -- ')
# prints 0 a -- 1 b -- 2 c

```

Instead, Python for loops are more like “for each” loops in some other  
languages, including VBA.

If you just want a loop counter alone, use range:

```
for i in range(10):
    print(i, end=' ')
# will print 0 1 2 3 4 5 6 7 8 9

for i in range(10, 101, 10):
    print(i, end=' ')
# will print 10 20 30 40 50 60 70 80 90 100

```

The signature of range is:

```
range(start=0, end, step=1)

```

where start defaults to 0, step defaults to 1, and end is excluded from  
the values generated. Note that range isn’t magic syntax, it actually  
returns an object holding a sequence of values:

```
>>> obj = range(10, 31, 5)
>>> len(obj)
5
>>> obj[0]
10
>>> obj[1]
15
>>> 21 in obj
False

```

The for each loop just iterates over the values of the range object.

---

<div class="post-metadata">

**Author:** ![Samuel](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/samuel/32/3209_2.png) [@Samuel](https://discuss.python.org/u/Samuel)\
**Post date:** [April 19, 2021, 4:14am UTC](https://discuss.python.org/t/python-for-loops-do-not-behave-as-expected/8279/4 "2021-04-19T04:14:15Z")

</div>

Thanks Guys. I’m catching on. Slowly, to be sure, but I think I’m getting it.

---

<div class="post-metadata">

**Author:** ![CAM-Gerlach](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/cam-gerlach/32/3688_2.png) [@CAM-Gerlach](https://discuss.python.org/u/CAM-Gerlach)\
**Post date:** [April 26, 2021, 9:04pm UTC](https://discuss.python.org/t/python-for-loops-do-not-behave-as-expected/8279/5 "2021-04-26T21:04:36Z")

</div>

I realize I’m rather late, and this may be a bit besides the point, but for situations like this, it is often simpler, more elegant and more performant to use Python’s [comprehensions](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions) feature. However, one important note: This will create a new list object, rather than modifying your existing one in place, which may or may not be what you want if you have other code that references it. See your [previous question](https://discuss.python.org/t/cannot-get-different-random-numbers/6392/20) for an excellent example of where this comes into play.

```python
NumList = [num + 1 for num in NumLst]

```

For reference, a corrected form of your original logic:

```python
for idx, num in enumerate(NumLst):
    NumLst[idx] = NumLst[idx] + 1

```
