As nneonneo's comment under Blake's answer (which describes a significant part of the problem) states, the code in the original post doesn't actually do what he states. For example:
def foo(A):
tmp = A
tmp = tmp + 1
return (A, tmp)
foo(3)
returns (3,4)
, meaning A has been left unchanged.
Where this would not be true is where A is a mutable type. Mutable types include lists, dictionaries, and derived types of those, while integers, floats, and tuples are not mutable.
For example:
def foo(A):
tmp = A
tmp[0] = tmp[0] + 1
return (A, tmp)
foo([1, 2])
which returns ([2, 2], [2, 2])
, and in this case A has changed.
That foo changes the value of A in the list case but not the integer case is because lists are mutable and integers are not. Assigning A to tmp when A is a mutable type assigns a reference to the mutable object, and changing one of its elements (as in tmp[0] = tmp[0] + 1
) doesn't make a new object.
If you do not want your function to have this side-effect-like behavior for a list, for example, a common Python idiom is to use slice notation to duplicate the list. This will make a new list object when you assign it to tmp that is a copy of the list object in A:
def foo(A):
tmp = A[:]
# this slice makes a new list, a copy of A
tmp[0] = tmp[0] + 1
return (A, tmp)
foo([1, 2])
This returns ([1, 2], [2, 2])
, so A is unchanged and tmp is changed.
There are other ways to copy lists or other mutable objects which are subtly different from each other. How to clone or copy a list? has a great description of your choices.