3

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.

4
  • 4
    It doesn't chance the string, it returns a new one. Commented Sep 3, 2018 at 10:32
  • Can you add the expected output? Commented Sep 3, 2018 at 10:33
  • 1
    What do you think is being changed here? Both i and a will be unchanged. Commented Sep 3, 2018 at 10:36
  • Immutable does not mean that you cannot get access to parts of the string and modify them. But this is a new object (a new string created) and the old object is still immutable and unchanged. Commented Sep 3, 2018 at 10:39

6 Answers 6

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

"once a string variable is assigned to a string (For eg a ='Hello') the contents of the string cannot be changed" => this has nothing to do with "being assigned to" a variable - a string is immutable, period.
3

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'

2 Comments

Well... to be fair - in ~15 years of Python I don't think I've ever used it (just have known it's there but never found a practical need...)
Thanks for your help
2
    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.

Comments

1

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]

Comments

1

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"

9 Comments

"One of the way to change the value on a string is to save it in an array." => this is not going to "change the value on a string", whatever "save it in an array" might be supposed to mean (I assume you actually meant "build a list from it").
If you create the string inside the array, instead of save it. It could works better.
what you wrote in your comment makes even less sense than your answer.
this might help: nedbatchelder.com/text/names.html (should be part of the official doc actually).
Oh and yes: there's nothing like a "primitive value" in Python. Strings are objects just like anything in Python (integers, lists, dicts, function, classes, modules, etc etc etc).
|
0

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

6 Comments

yes they are immutable because the second line creates a new string. s is only a name or label assigned to the string. In the first line s is assigned to 'Hello World'. In the second line s is assigned to the new string 'Heiio Worid'. The original string 'Hello World' is still there, but is not assigned to any variable and will therefore be removed from memory by the garbage collector. Neither of the strings have changed, only the variables are reassigned.
Thank you for the explanation. But would this work in Java? I get that a new object needs to be created but does that happen so automatically in Java? Java also has a garbage collector. But I think this still wouldn't work without explicitly creating new objects. Python is just too fancy man...
Java apparently works exactly the same: String a = "banana"; System.out.println(a); a = a.toUpperCase(); a = a.replace('A', 'O'); System.out.println(a); gives banana and BONONO.
So when a.toUpperCase() returns a string, the assignment statement creates a new object, allocating memory for it, then assigns the address to be pointed to by the variable a? (which no longer points to the previous string object). So the previous object is used to get the data and create a new string out of it, then it will be thrown away since nothing points to it anymore. So each time, you are instantiating a new object and essentially throwing away the old one (assuming you use the same variable name to point to the objects like we are doing).
I guess if it can do all that, then it should be able to make a copy of the object and use the index (or indices) to replace parts of the string, and use the same process.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.