laika222
12/22/2018 - 7:53 PM

References

################################
### REFERENCES ###
################################

# Python uses references whenever a variable must store values of mutable data types, such as lists or dictionaries. For values with immutable
# data types such as strings, integers, or tuples, Python will store the value itself into the variable.

# When you set one variable equal to another, it duplicates the value into the second variable, but the variables remain separate entities.

firstVariable = 42
secondVariable = firstVariable # set secondVariable using value from firstVariable
firstVariable = 100 # change value of firstVariable (doesn't affect secondVariable)

firstVariable # result is 100, since this was changed
secondVariable # result is 42, still 42 since this wasn't changed when firstVariable was changed

# However, lists don't function in this way. When you assign a list to a variable, the variable holds a *reference* to the list, 
# but doesn't actually copy the list value over. If you change the list, it'll change all of the variables that reference that list.

firstVariable = [0, 1, 2, 3, 4]
secondVariable = firstVariable # place firstVariable *reference* into secondVariable, but doesn't actually copy over values
firstVariable[3] = 100000 # change firstVarable, will also affect secondVariable since that variable references the same list

firstVariable # result is [0, 1, 2, 100000, 4]
secondVariable # result is [0, 1, 2, 100000, 4]

################################
### PASSING REFERENCES ###
################################

# References are important for understanding how arguments get passed to functions. When a function is called, the values of the arguments
# are copied to the parameter variables. For lists and dictionaryies, this means a copy of the references is used in the parameter.

def myFunction(someParameter):            # define function myFunction with argument someParameter
    someParameter.append('hello')   # when function is called, append value of 'hello'

myList = [1, 2, 3]      # set myList to this list
myFunction(myList)      # call myFunction, passing in myList as the argument, at which point the function will append 'hello'
print(myList)             # result is [1, 2, 3, 'hello'], note that 'hello' has been appended to myList, since a reference (and not the actual values) was passed to the function

# While passing around references is often the handiest way to deal with lists and dictionaries, if the function modifies the list or
# dicionary that is passed, you may not want these changes in the original list or dictionary value. For this, Python provides a module
# called copy that provides both the copy() and deepcopy() functions. The first of these, copy.copy(), can be used to make a duplicate
# copy of a mutable value like a list or dictionary, and not just a copy of a reference.

# Remember that this happened when a reference was passed:

firstVariable = [0, 1, 2, 3, 4]
secondVariable = firstVariable # place firstVariable *reference* into secondVariable, but doesn't actually copy over values
firstVariable[3] = 100000 # change firstVarable, will also affect secondVariable since that variable references the same list

firstVariable # result is [0, 1, 2, 100000, 4]
secondVariable # result is [0, 1, 2, 100000, 4]

# However, if you use copy.copy():

import copy # import the copy library
firstVariable = [0, 1, 2, 3, 4]
secondVariable = copy.copy(firstVariable) # copy the list from firstVariable into secondVariable (i.e. don't pass the reference)
firstVariable[3] = 100000 # change firstVarable, will will *not* affect secondVariable since that variable used copy.copy()

firstVariable # result is [0, 1, 2, 100000, 4]
secondVariable # result is [0, 1, 2, 3, 4], since secondVariable was copied instead of a reference being passed, and therefore it wasn't changed when firstVariable was changed