Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying a string while looping on it

Here we modify the string s while looping on it:

s = 'hello'
for c in s:
    s += c
    print(s)

It doesn't generate an infinite loop (it could: we add a new character in each iteration!).

I know this since years, but I can't really explain why. Has this something to do with string immutability or is it not related?

When doing for c in s:, is the original s copied in memory before starting the loop?


Another case that I thought could generate an infinite loop, but it does not:

s = 'hello'
def f(x):
    i = 0
    while True:
        try:
            yield x[i]
        except IndexError:
            break
        i += 1

for c in f(s):
    s += c
    print(s)
like image 765
Basj Avatar asked Apr 13 '20 15:04

Basj


2 Answers

It doesn't generate an infinite loop (it could: we add a new character in each iteration!).

It is because strings in Python are immutable. When you do for c in s, for loop iterates over original object (object containing "hello") and when you do s += c, a new string is created and hence, you aren't modifying the original string object that for loop is still iterating over.

Also, adding @Steven Rumbalski 's comment in my answer:

It iterates over the original object. Rebinding the name to a new object doesn't change the for-loop because it doesn't resolve the name on each iteration.

Now, Let's talk about second example of yours:

If you call your function f(s), it makes it's formal argument x to point to the object containing the string "hello" and it creates a generator using the string object. Now, subsequent re-assignment of the string s (using s += c) actually creates another string and doesn't effect the original object. Your function's formal argument is still pointing to an object containing "hello".

So, after first iteration of your for loop in the second example:

  1. Formal argument of function f(x) will be still pointing to an object containing "hello".

  2. s will be pointing to an object containing "helloh".

IMPORTANT:

However, if you try your code with mutable data types, it may create an infinite loop. See this:

li = [ 1, 2, 3, 4 ]
for i in li:
    li.append(i)
    print(li)
like image 175
abhiarora Avatar answered Oct 22 '22 13:10

abhiarora


Mutate a list to accomplish what you want.

array = list('hello')
for c in array:
    array.append(c)
    print(*array, sep='')

prints

helloh
hellohe
hellohel
hellohell
hellohello
hellohelloh
hellohellohe
hellohellohel
hellohellohell
hellohellohello
hellohellohelloh
hellohellohellohe
...

If you want to loop by one character continuously you can do

from itertools import cycle

for c in cycle('hello'):
    print(c)

prints

h
e
l
l
o
h
e
l
...
like image 1
Steven Rumbalski Avatar answered Oct 22 '22 15:10

Steven Rumbalski