<jupyter_start><jupyter_text>Shared References and Mutability The following sets up a shared reference between the variables my_var_1 and my_var_2<jupyter_code>my_var_1 = 'hello'
my_var_2 = my_var_1
print(my_var_1)
print(my_var_2)
print(hex(id(my_var_1)))
print(hex(id(my_var_2)))
my_var_2 = my_var_2 + ' world!'
print(hex(id(my_var_1)))
print(hex(id(my_var_2)))<jupyter_output>0x24c9144ca08
0x24c9144fab0<jupyter_text>Be careful if the variable type is mutable!Here we create a list (*my_list_1*) and create a variable (*my_list_2*) referencing the same list object:<jupyter_code>my_list_1 = [1, 2, 3]
my_list_2 = my_list_1
print(my_list_1)
print(my_list_2)<jupyter_output>[1, 2, 3]
[1, 2, 3]<jupyter_text>As we can see they have the same memory address (shared reference):<jupyter_code>print(hex(id(my_list_1)))
print(hex(id(my_list_2)))<jupyter_output>0x24c9144fc48
0x24c9144fc48<jupyter_text>Now we modify the list referenced by *my_list_2*:<jupyter_code>my_list_2.append(4)<jupyter_output><empty_output><jupyter_text>*my_list_2* has been modified:<jupyter_code>print(my_list_2)<jupyter_output>[1, 2, 3, 4]<jupyter_text>And since my_list_1 references the same list object, it has also changed:<jupyter_code>print(my_list_1)<jupyter_output>[1, 2, 3, 4]<jupyter_text>As you can see, both variables still share the same reference:<jupyter_code>print(hex(id(my_list_1)))
print(hex(id(my_list_2)))<jupyter_output>0x24c9144fc48
0x24c9144fc48<jupyter_text>Behind the scenes with Python's memory manager---- Recall from a few lectures back:<jupyter_code>a = 10
b = 10
print(hex(id(a)))
print(hex(id(b)))<jupyter_output>0x7559eaf0
0x7559eaf0<jupyter_text>Same memory address!!This is safe for Python to do because integer objects are **immutable**. So, even though *a* and *b* initially shared the same memory address, we can never modify *a*'s value by "modifying" *b*'s value. The only way to change *b*'s value is to change it's reference, which will never affect *a*.<jupyter_code>b = 15
print(hex(id(a)))
print(hex(id(b)))<jupyter_output>0x7559eaf0
0x7559eb90<jupyter_text>However, for mutable objects, Python's memory manager does not do this, since that would **not** be safe.<jupyter_code>my_list_1 = [1, 2, 3]
my_list_2 = [1, 2 , 3]<jupyter_output><empty_output><jupyter_text>As you can see, although the two variables were assigned identical "contents", the memory addresses are not the same:<jupyter_code>print(hex(id(my_list_1)))
print(hex(id(my_list_2)))<jupyter_output>0x24c9146c5c8
0x24c913c6848
{'fraction_non_alphanumeric': 0.1157684630738523, 'fraction_numerical': 0.06427145708582835, 'mean_word_length': 8.827450980392157, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '193067', 'license': 'MIT', 'n_tokens_mistral': 1083, 'n_tokens_neox': 1007, 'n_words': 233, 'path': 'FCP Review/Variables and Memory/06 - Shared References and Mutability.ipynb', 'repo_name': 'Rafiei-tayebe/AP4002', 'size': '2505'}