2

I just had a problem with Python which I eventually fixed myself. Although I'm still wondering what's the difference of using

arrayName

and

arrayName[:]

even if they have the same values. Here's my code where I had the problem:

def quickSort(ar, start, end):
    count = 0
    if end - start >= 2:
        p = ar[end-1]
        pos = start
        for i in range(start, end-1):
            if ar[i] < p:
                if i != pos:
                    ar[i], ar[pos] = ar[pos], ar[i]
                pos += 1
                count += 1
        ar[pos], ar[end-1] = ar[end-1], ar[pos]
        count += 1
        count += quickSort(ar, start, pos)
        count += quickSort(ar, pos+1, end)
    return count

def insertion_sort(ar):
    shift = 0
    for i in range(1, len(ar)):
        j = i-1 
        key = ar[i]
        while (j > -1) and (ar[j] > key):
            ar[j+1] = ar[j]
            shift += 1
            j -= 1
        ar[j+1] = key
    return shift

n = int(input())
ar = list(map(int, input().split()))
print(insertion_sort(ar) - quickSort(ar, 0, n))

The above will print -18 but if I change the last line into

print(insertion_sort(ar[:]) - quickSort(ar[:], 0, n))

it will print 1 which is the correct (the return value of insertion_sort() is 9 and the return value of quickSort() is 8). Why is it returning a wrong value when I didn't use list slicing?

johnjullies
  • 745
  • 1
  • 8
  • 22

1 Answers1

3

The [:] notation is a known "syntactic sugar" to duplicate the list (it's not an array).

It's a slice that takes the whole list - effectively duplicating it.

In your code you are not passing the same list when you use the ar[:] notation - you're passing an entirely new list (with the same members). This way each frame in the quickSort recursion has it's own, exclusive list (ar).

This does not happen when you pass the original list as is - which is mutable. Letting two (or way more...) frames modify the same list causes havoc.

Community
  • 1
  • 1
Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88
  • Note: it does duplicate the list (and is particulary useful when modifying a list inside a loop) but it is good to know the syntax `del mylist[:]` does empty the list (and not a copy of the list). – bufh Jul 20 '15 at 21:24
  • @bufh I did not see `del` used in this code so this is not in the scope of the question. In this particular case it's frames we worry about - since `quicksort` is a recursive function. – Reut Sharabani Jul 20 '15 at 21:25
  • it was not a critic, just something to let know to the user about the `[:]` syntax. – bufh Jul 20 '15 at 21:29
  • @bufh cool, I think there is a question popular question about it as well – Reut Sharabani Jul 20 '15 at 21:30
  • I understand it makes a duplicate but why is it still causing havoc if I make a variable? like `ar = list(map(int, input().split()))` `copy1 = ar` `copy2 = ar` `print(insertion_sort(copy1) - quickSort(copy2, 0, n))` – johnjullies Jul 21 '15 at 15:59