0

In the following algorithm when I am using permutation.append(array) in base case it just copies around the same thing. But when I try array[:] which I think is the same thing it works correctly. I am not sure for the reason. Can someone explain what's going on

def getPermutations(array):
        # Write yor code here.
        permutation=[]
        perm(0, array, permutation)
        print(permutation)
        return permutation
    
    
    def perm(i, array, permutation):
        if i==len(array)-1:
            print(array)
            permutation.append(array)
            print(permutation)
        else:
            for j in range(i, len(array)):
                swap(array,i,j)
                perm(i+1, array, permutation)
                swap(array,i,j)
    
    def swap(array, i, j):
        array[i], array[j]=array[j], array[i]
Muhteva
  • 2,729
  • 2
  • 9
  • 21
  • Does this answer your question? [List changes unexpectedly after assignment. Why is this and how can I prevent it?](https://stackoverflow.com/questions/2612802/list-changes-unexpectedly-after-assignment-why-is-this-and-how-can-i-prevent-it) – MisterMiyagi Oct 21 '21 at 08:54
  • The short answer is that using the array variable name as is only copies the reference to the array, such that any changes you'll make (adding/deleting elements) will be applied on the same array of the caller function, while the `[:]` operation creates a new copy of the array, such that the adding/deleting operations won't be applied on the caller's array. The elements themselves, however, may still be shared between the two arrays, since the copy is shallow, so changing an element's attribute in one array may be reflected on the other array too (irrelevant for immutable objects). – SomethingSomething Oct 21 '21 at 09:12
  • `array[:]` creates a *copy* of the list. If you don't do that, then no copy is made. – juanpa.arrivillaga Oct 21 '21 at 09:28
  • 1
    @SomethingSomething it's best not to say that `array` makes *any copy at all*. – juanpa.arrivillaga Oct 21 '21 at 09:28
  • @juanpa.arrivillaga you can sometimes say that sending a variable by reference is just like sending a pointer/reference by value :P – SomethingSomething Oct 21 '21 at 09:30

1 Answers1

2

array[:] shallow-copies the current array whereas array is a reference to the array object itself. To visualize, when you use permutation.append(array), your list can be visualized like this: enter image description here

If you use permutation.append(array[:]), your list will be like this:

enter image description here Difference between shallow-copy and deep-copy:

A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.

A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original

Reference: https://docs.python.org/3/library/copy.html

Notice that since our array consists of immutable data types, there is no difference in this case between deep and shallow copy. You just create the copy of the array.

Extra

To better explain the difference between a copy and the original object, please inspect the code below carefully.
a = [1,2,3,4,5,6,7]
a_copy = a   # a_copy refers to the same object as a  (array case)
b_copy = a[:] # b_copy refers to the copy of the a (array[:] case)
a_copy.append(8)
print(a_copy)
print(b_copy)

Output:

[1, 2, 3, 4, 5, 6, 7, 8]  # a_copy
[1, 2, 3, 4, 5, 6, 7]     # b_copy
Muhteva
  • 2,729
  • 2
  • 9
  • 21
  • 1
    I'd call the "primitive" data types "immutable", since there aren't really primitives in Python, even float and int are objects that are stored on the heap, they're just immutable. When you write `a = 0` and then `a += 1`, you don't really increment existing integer variable - what really happens is that a new integer is created on the heap and `a` is assigned with its new reference. Same for str, float, etc. – SomethingSomething Oct 21 '21 at 09:19