2

I was studying merge sort and I wrote this code

def mergesort(a): #sorting algo
    #code is alright just confused about scope of variable
    if(len(a)>1):
        mid = len(a)//2
        l = a[:mid]
        r = a[mid:]
        mergesort(l)
        mergesort(r)
        i=j=k=0
        while(i<len(l) and j<len(r)):
            if(l[i]>r[j]):
                a[k] = r[j]
                j+=1
            else:
                a[k] = l[i]
                i+=1
            k+=1
        
        while(i<len(l)):
            a[k] = l[i]
            i+=1
            k+=1

        while(j<len(r)):
            a[k] = r[j]
            j+=1
            k+=1        

a = [30,2,4,5,-1,3,7,3,9,2,5]
mergesort(a)
print(a)

here a is a global variable, but when the function parameter name is also a doesn't the a in function scope override the a in the global scope? how the global variable is getting edited inside mergesort function?

I tried another code with same approach but here the global variable doesn't get edited(as expected),how is this different from the above code?

def foo(a):
    a=20

a = 10
foo(a)
print(a)
Manoj D Bhat
  • 2,300
  • 1
  • 6
  • 11

2 Answers2

1

The problem is not that a is global (because it's not). The a is local to the function, but it references the same list as the global a (because variables are passed by reference in python).

a is a list (which is mutable) in the first example, while a is an integer (which is immutable) in the second example. So changing values inside of the list (like a[k] = l[i]), changes the global list as well, while changing the reference to an integer (like a = 20) only replaces the local reference.

If you don't want the function to change the global list, you can fix it by creating a copy of the list:

def mergesort(a):
    a = a[:] # or a = a.copy(), whichever you prefer
    ...

Note that in this case, the function has no effect, so you'd probably want to return the resulting list.

Yevhen Kuzmovych
  • 10,940
  • 7
  • 28
  • 48
  • That's not really a "fix". OP's function doesn't return anything, so copying the list means that it has no effect. – wjandrea Sep 14 '22 at 15:03
  • @wjandrea Yes, you're right, this function wouldn't have any effect as it is now. But if OP was concerned that it changes the global list, he might want this function to return something after all. I'll update the answer to be a bit clearer. – Yevhen Kuzmovych Sep 14 '22 at 16:17
  • Totally, you'd just need to add `return a` at the end and capture the recursive results. – wjandrea Sep 14 '22 at 16:21
1

Lists are mutable but int is not. So when you change int, you get an entirely new int. When you make changes within a list, you don't get a new list. You just have a modified list.

So when you pass the list to a function, it does not create a new list unless you do something like this: a.copy() or a[:] which creates a new list. In your case, you are using the same list as outside the function.

For more info read about mutability of data types or pass by reference and pass by value.