Python strings - immutability of strings

Viewed 2717

I want to know that if Python strings are immutable then why does this piece of code works and how it works.

a = input()
for i in a:
    if i.isupper():
        print(i.lower(), end='')
    else:
        print(i.upper(), end='')

This changes the characters in the string. Before as I knew that strings are immutable I used to convert it in list and then change it and join the list back to string. Now I think all the code I had written back then was worthless effort.

6 Answers

str.lower, str.upper and other string operations return copies. They do not work in place. You can check this yourself by reading the documentation; for example:

str.lower()

Return a copy of the string with all the cased characters converted to lowercase.

A copy here implies a new string, not the old one mutated in place. You can additionally verify this by printing a string after mutating it:

x = 'HELLO'
y = x.lower()
print(x)  # 'HELLO'

Strings in Python are immutable which means that once a string variable is assigned to a string (For eg a ='Hello') the contents of the string cannot be changed unlike the list object. In the code above you are in a way transforming your string and not changing the contents of your string variable.

a=input()
for i in a:
    if i.isupper():
        print (i.lower(),end='')
    else:
    print (i.upper(),end='')
print(a)

If you would run this code you will see that the value of a is the same which you entered. The strings methods lower() and upper() just returns a copy of the string.

You are right, strings are immutable. You have to understand how the methods that you call works.

if i.isupper():
        print (i.lower(),end='')
    else:
        print (i.upper(),end='')

The method lower() returns a copy of the string in which all case-based characters have been lowercased.

So this methods returns a copy, not the original one. It will returns the original one only when the word used is all in lower case, and in this case it will return the original string. Not the new copy of it ( a new variable.)

For the upper is the same, they create a new variable.

Thanks to bruno desthuilliers to add this valuable link to understand more about "Facts and myths about Python names and values"

They are immutable. Eg

text = 'hello'
text.upper()
print(text) # hello

Though you have called upper on the text variable, it's value has not changed. Contrast with a list, which is mutable

lst = [1,2,3]
lst.append(4)
print(lst) # [1,2,3,4]
    a = input()

    for i in a:
        if i.isupper():
            print(i.lower(), end='')
        else:
            print(i.upper(), end='')

A string is immutable because we can't change its value after defining it. Furthermore, once we assign a value to a string, it receives an id based on that value we assigned. Hence if we change the value of that string, it causes to change its id. Therefore, strings are immutable.

They are not mutable. You can't modify the parts of a string by index. and most string functions return a new string from an existing string, so a new object must be created if you want to store the newly returned string. The original string is either unaffected, or is lost if the variable that pointed to it is changed to point to something else (like the new string object).

BUT, what about appending a string literal to an existing string object? like:

a = 'great'
a+= ' day'
print(a)

now in this case below, I am returning a new string and creating a new object, the old string will be picked up by garbage collector

s = 'Hello World'

s = s.replace('l','i')

print(s)

a = 'banana'
x = ''

for i in range(len(a)):
    if i == 4:
        x+='t'
    else:
        x+=a[i]   #not mutating a, since i clearly made a new object
                    #but then is this concatenation not considered mutation,
                            #or is x also being "recreated"?

print(x)

a = a + x   #appending something to original object, or am i creating a new one?

print(a)

What else you can do (this is definitely not mutation):

a = 'banana'
print(a)

for i in a:
    if i.isupper():
        print(i.lower(), end='')
        print(i,end = '')
    else:
        print(i.upper(), end='')
        print(i,end = '')

a = a.upper()
print('\n'+a)
for i in a:
    if i.isupper():
        print(i.lower(), end='')
        print(i,end = '')
    else:
        print(i.upper(), end='')
        print(i,end = '')

a = a.lower()
print('\n'+a)

ls = [] 

for j in range(len(a)):
    if a[j].isupper():
        ls.append(a[j].lower())
    else:
        ls.append(a[j].upper())
print(ls)

s = ''
a = s.join(ls)
print(a)

Output:

banana
BbAaNnAaNnAa
BANANA
bBaAnNaAnNaA
banana
['B', 'A', 'N', 'A', 'N', 'A']
BANANA
Related