Passing mutable objects as "value" in Python

In Python if you pass any object, it depends on the following factor if it's going to behave as "Pass by value" or "Pass by reference".

  1. Mutable object:

If the object is mutable, it's going to behave like "Pass by reference".
This means inner function call can change the value in your object (which will also reflect in your upper function)

def change_value(s):  
    s = s + ' !'


s = 'yask'

change_value(s)

print s

----
yask  
  1. Immutable object:

However, if you pass immutable object, it will behave like "Pass by value".

def change_value(s):  
    s = s.append(' !')


s = ['y', 'a', 's', 'k']

change_value(s)

print s  
----
['y', 'a', 's', 'k', ' !']

But what if you want to use a mutable object (like a list) and
"pass like value"?

I was solving this Palindromic partion problem where I had to return all such possible partitions which were all palindromic.

This is an interesting problem because here I needed two types of variables to be passed (in a recursive function).

current_partition : This variable contains a "possible" answer (which might be true or not, we don't know as yet.. only if we are able to partition everything we would know if our way of partitioning is correct and this we could add it to our final result.

So this needs to be passed by "value".

final_result: This variable contains the final result. Inner recursive calls can reach the base case and add the current_parition to the final_result.

So this needs to be passed by "reference".

To pass mutable object by reference you don't have do to anything special.

For passing by reference you can "copy" the content of variable and pass that variable in the inner function.
That way, if inner function changes the value, it won't reflect on the variable in the upper function as it was never passed. Only it's copied values were passed.

Here is the solution I wrote for the above problem.

def partition(index, arr, current_parition, result):  
    if index == len(arr):
        result.append(current_parition)
        return True

    for i in range(index , len(arr)):
        substr = arr[index: i + 1]
        if is_palin(substr):

            current_parition.append(substr)
            partition(i + 1, arr, current_parition[:], result)

            current_parition.pop()

    return result


def is_palin(arr):  
    s = 0
    e = len(arr) - 1

    while s < e:
        if arr[s] != arr[e]:
            return False
        s += 1
        e -= 1

    return True
arr = 'aab'  
print partition(0,arr, [], [])

Instead of passing the variable, create a clone of the variable first and then pass that.

In short, you can write it like this:

def change_value(s):  
    s = s.append(' !')


s = ['y', 'a', 's', 'k']

change_value(s[:])

print s