GeoGeoGeometry - 1 year ago 72

Python Question

I'm working with python 3.5, and insert isn't behaving as I expect it to.

`scorelist = ["x","x"]`

for q in range(0, len(scorelist)):

if scorelist[q] == "x":

scorelist.insert((q), " ")

I'd expect that to leave the least reading as follows

`scorelist = ["x", " ", "x", " "]`

Instead, it leaves me with

`scorelist = [" ", " ", "x", "x"]`

I'm pretty stumped as to why this is the output. Any guidance would be greatly appreciated.

Recommended for you: Get network issues from **WhatsUp Gold**. **Not end users.**

Answer Source

It's generally a Bad Idea to mutate any container while iterating over it.

In your case, `len(scorelist)`

is evaluated once, at the time the `for`

loop begins. The length is 2 at that time, so the range is just `[0, 1]`

. Nothing later can possibly change that.

In the first iteration, `q`

is 0, and `scorelist[0]`

is `"x"`

, so

```
scorelist.insert(0, " ")
```

leaves `scorelist`

as

```
[" ", "x", "x"]
```

In the second iteration, `q`

is 1, and for the new value of `scorelist`

, `scorelist[1]`

is still `"x"`

, so

```
scorelist.insert(1, " ")
```

leaves `scorelist`

as

```
[" ", " ", "x", "x"]
```

Then the loop ends. There's nothing really mysterious about it, but it's far from obvious either - which is *why* it's a Bad Idea to mutate containers while iterating over them ;-)

If you're determined to insert a blank at the end, and between every pair of elements before that, here's one obscure way to do it:

```
for q in reversed(range(1, len(scorelist) + 1)):
scorelist.insert(q, " ")
```

Then, e.g., if `scorelist`

starts as

```
['x', 'y', 'z']
```

that loop will leave it as

```
['x', ' ', 'y', ' ', 'z', ' ']
```

By iterating "backwards", the insertions don't interfere with the original indices of the original list elements. If that's confusing (hint: it is! ;-) ), just work it out one iteration at a time, as I spelled it out for your original code.