2

I am experiencing a behavior that from what I've hear is common in Python, but I'd like to know this is the default, and how to prevent this. Consider the following code:

dic1 = {'a':1, 'b':2}
lis1 = [1, 2]

def somefunc(dic):
    dic.update({'b':20})
    return dic

def otherfunc(lis):
    lis.append(20)
    return lis

for i in range(3):
    dic2 = dic1
    lis2 = lis1
    print(dic2)
    somefunc(dic2)
    print(lis2)
    otherfunc(lis2)

We I run this code, it outputs

{'a': 1, 'b': 2}
[1, 2]
{'a': 1, 'b': 20}
[1, 2, 20]
{'a': 1, 'b': 20}
[1, 2, 20, 20]

but why doesn't it output the following?

{'a': 1, 'b': 2}
[1, 2]
{'a': 1, 'b': 2}
[1, 2]
{'a': 1, 'b': 2}
[1, 2]

I feel it should output this since I am resetting dic2 and lis2. Why is this the default behavior? Shouldn't Python make a copy of dic2 once it enters the function? Shouldn't dic2=dic1 create a copy of dic1, instead of creating a different pointer to the same place in memory? (if that's indeed what's happening)

I can prevent this behavior from occurring with dic1 by replacing dic2 = dic1 with dic2 = dic1.copy() (or adding dic=dic.copy() to the function), but how do I do it with lists? They don't have a copy method. Furthermore, is there a way for me to prevent this by default, without having to remember to use the copy method every time I deal with dictionaries (or maybe even Pandas dataframes and so on) inside a function?

Cheers

TomCho
  • 3,204
  • 6
  • 32
  • 83
  • All values in Python are passed by reference. See this http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference for a more complete explanation. – JSTL May 30 '16 at 19:11

1 Answers1

1

on Python, lists are mutable, this means that lis2 is just another name for lis1, thus they are the same object

here are 2 ways to make a copy of lis1 on lis2:

lis2 = lis1[:]

lis2 = list(lis1)

I'd prefer using list() since it's more readable.

Rosa Alejandra
  • 732
  • 5
  • 21