0

Scenario 1 : Mutable object like list

def a(l):
    l[0] = 1
    print("\nValue of l = {0} in a()".format(l))

def b(l):
    l = l + [9]
    print("\nValue of l = {0} in b()".format(l))

l = [0]

a(l)
print("\nValue of l = {0} after executing a()".format(l))
b(l)
print("\nValue of l = {0} after executing b()".format(l))

Output

Value of l = [1] in a()
Value of l = [1] after executing a()
Value of l = [1, 9] in b()
Value of l = [1] after executing b()

Questions

  • In the context of mutable objects, why is the modification done to l in b() not visible in global scope whereas it happens for a()?

Scenario 2 : Immutable object like integer

def a(l):
    l = 1
    print("\nValue of l = {0} in a()".format(l))
def b(l):
    l = l + 9
    print("\nValue of l = {0} in b()".format(l))

l = 0

a(l)
print("\nValue of l = {0} after executing a()".format(l))
b(l)
print("\nValue of l = {0} after executing b()".format(l))

Output

Value of l = 1 in a()
Value of l = 0 after executing a()
Value of l = 9 in b()
Value of l = 0 after executing b()

Questions

  • In the context of immutable objects, why is the modification done to l in both a() and b() not visible in the global scope?

I checked with many folks and they couldnt explain this. Can someone explain the fundamental concepts used in this example?

GeorgeOfTheRF
  • 8,244
  • 23
  • 57
  • 80
  • The premise is wrong. You are creating new local objects. In `b`, try using `.append` instead - the list is mutable, and that will modify the list in-place, as opposed to creating a new object. If you want to reference variables in the global namespace, you should use the `global` keyword at the top of your function. Python creates a separate space for local keywords within functions... I'll just write an answer. – Zizouz212 Aug 03 '18 at 03:53
  • 1
    The fundamental principle you’re missing is the difference between values and names. I’m not sure which question this is a duplicate of, but there are a few with great answers that explain it. Briefly, `l[0] =` is modifying the value that `l` names, but `l =`is just making `l` name a different value. That’s the difference between the first example and the other three examples. – abarnert Aug 03 '18 at 03:59
  • @Zizouz212 You mean to say l = l + [9] creates a new local object and l.append(9) doesnt ? Why is that? Will look forward for your answer. – GeorgeOfTheRF Aug 03 '18 at 04:00
  • I think the top few answers on the first linked duplicate will explain everything you're asking. Some of the others are closer questions to your question, but the answers aren't as good (which is why most of them ended up being closed as duplicates of the first one). – abarnert Aug 03 '18 at 04:06
  • The only thing missing is the fact that the `+` operator _never_ modifies anything in Python, it _always_ returns a new object. (Technically, you _could_ write a class with an `__add__` method that modifies `self`, but that would be confusing and deeply unpythonic.) So, `l = l + [0]` is just a special case of that general rule: `l + [0]` returns a new object, and then `l =` just assigns that new object to your local variable `l`, the same as if you'd written, say, `l = 2`. I can't find a dup that covers that part. – abarnert Aug 03 '18 at 04:08
  • The combination if +, local/global and mutable/immutable is something which even many veterans doesnt understand. Like you said, I dont think this is the exact duplicate of other existing answers because other answers are missing the + part etc. So can you not mark it as duplicate since then nobody can post an answer. @Zizouz212 was about to write an answer before you closed this thread. Hope you understand. – GeorgeOfTheRF Aug 03 '18 at 04:14
  • @ML_Pro That first question "How to pass by reference?" answers this nicely. If you want to test if your object is the same, you can use the `id` function - which IIRC, kind of returns the memory address of that object. For immutable objects, that doesn't change, unless you perform an operation that creates a new object and overwrites the original. While this isn't a concept necessarily embedded in Python, you may enjoy reading the difference between classes and structures - that could differentiate pass by value, versus pass by reference. – Zizouz212 Aug 03 '18 at 04:17
  • @ML_Pro It’s not true that many veterans don’t understand how `+` interacts with local/global and mutable/immutable. Every veteran—even every intermediate Python user—knows that `+` doesn’t mutate, so the question arises. So the only thing and answer to this question could really do is duplicate or reference the top answer on the first questions, and then add that all of this is irrelevant because you’re using `+` which doesn’t mutate anything. I don’t think that’s an answer that would make SO better. Whereas having your question linked to the existing answer does. – abarnert Aug 04 '18 at 01:30

0 Answers0