I've spent the last 2 hours on this and I've probably read every question on here relating to variables being passed to functions. My issue is the common one of the parameter/argument being affected by changes made inside the function, even though I have removed the reference/alias by using variable_cloned = variable[:]
in the function to copy the contents across without the reference.
Here is the code:
def add_column(m):
#this should "clone" m without passing any reference on
m_cloned = m[:]
for index, element in enumerate(m_cloned):
# parameter m can be seen changing along with m_cloned even
# though 'm' is not touched during this function except to
# pass it's contents onto 'm_cloned'
print "This is parameter 'm' during the for loop...", m
m_cloned[index] += [0]
print "This is parameter 'm' at end of for loop...", m
print "This is variable 'm_cloned' at end of for loop...", m_cloned
print "m_cloned is m =", m_cloned is m, "implies there is no reference"
return m_cloned
matrix = [[3, 2], [5, 1], [4, 7]]
print "\n"
print "Variable 'matrix' before function:", matrix
print "\n"
add_column(matrix)
print "\n"
print "Variable 'matrix' after function:", matrix
What I'm noticing is that the parameter 'm' in the function is changing as if is an alias of m_cloned - but as far as I can tell I have removed the alias with the first line of the function. Everywhere else I have looked online seems to suggest that this line will make sure there is no reference to parameter - but it's not working.
I'm sure I must have made a simple mistake but after 2 hours I don't think I'm going to find it.
Pass-by-reference means to pass the reference of an argument in the calling function to the corresponding formal parameter of the called function. The called function can modify the value of the argument by using its reference passed in.
The call by reference method of passing arguments to a function copies the address of an argument into the formal parameter. Inside the function, the address is used to access the actual argument used in the call. It means the changes made to the parameter affect the passed argument.
Solution 1. You can replace $@ with $1 if you only want the first argument. This creates a temporary function f , which is passed the arguments (note that f is called at the very end). The unset -f removes the function definition as the alias is executed so it doesn't hang around afterwards.
Bash users need to understand that alias cannot take arguments and parameters. But we can use functions to take arguments and parameters while using alias commands.
It looks like you need a deepcopy, instead of a shallow copy, which is what [:]
gives you:
from copy import deepcopy
list2 = deepcopy(list1)
Here's a longer example comparing the two types of copy:
from copy import deepcopy
list1 = [[1], [1]]
list2 = list1[:] # while id(list1) != id(list2), it's items have the same id()s
list3 = deepcopy(list1)
list1[0] += [3]
print list1
print list2
print list3
Outputs:
[[1, 3], [1]] # list1
[[1, 3], [1]] # list2
[[1], [1]] # list3 - unaffected by reference-madness
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With