{"assignment":{"_schema_version":2,"course_id":37,"date_created":"2022-06-28T19:00:00+00:00","date_modified":"2025-08-17T18:02:46.965217+00:00","extra_instructor_files":"","extra_starting_files":"","forked_id":null,"forked_version":null,"hidden":false,"id":1053,"instructions":"## What is Mutability?\n\n- Mutability: The value itself can change.\n- Immutability: Only new values can be produced, based on that value.\n\nMutability is an important concept now that we have more advanced data structures.\nFundamentally, the idea is whether values of the given type can change their inherent value, or if the value cannot change what it is.\nWhen we store values into variables, we often need to consider whether that variable is holding a mutable value.\nMany kinds of bugs can occur when we try to use an immutable value mutably or a mutable value immutably.\n\n## Mutability of Types\n\n* Immutable: Strings, floats, integers, booleans\n* Mutable: Lists, Dataclass\n\nStrings and lists are similar because they are both sequences of elements \u2013 you can index them, subscript them, perform membership tests on them, and many other common actions.\nHowever, a big difference between them is their Mutability.\nStrings are immutable while lists are mutable.\nIntegers and other primitive types are all immutable, in fact, while lists and dataclasses are mutable.\n\n## Immutable Primitives\n\n```python example-primitives\nname = \"Ada Bart\"\nprint(name)\n\n# The following line doesn't change `name`\nname.lower() \nprint(name)\n\n# The following line doesn't change `name`\nlowered_name = name.lower() \nprint(lowered_name)\nprint(name)\n\n# Now `name` has been changed!\nname = name.lower() \nprint(name)\n```\n\nSay you have a string variable.\nWhen you add another string to that variable's value, you need to assign the result - otherwise the combined value is lost.\nSimilarly, when you call a string method, you need to assign the result - otherwise the new value is lost.\nThis is the idea of immutability - you are never changing the string; you are simply creating new strings instead.\nIntegers and floats follow the same principle: you cannot fundamentally turn the value `5` into a different integer; you are always creating new integers based on the old one, but you cannot change the fact that `5` is `5`.\n\n## Mutable Lists\n\n```python example-list\ngrades = [90, 65, 78]\nprint(grades)\n\n# This adds 98 to the list\ngrades.append(98)\nprint(grades)\n\n# Bad! We add 44, but then overwrite the variable\n#   `grades` with None, which is returned by `.append()`\ngrades = grades.append(44)\nprint(grades)\n```\n\nNow say you have a list variable.\nAppending a value to the list fundamentally changes the list value itself, so that the list has a different sequence of values inside.\nThis is the idea of mutability, the fact that the list itself can change.\n\nA tricky thing to remember with lists is that if you append a value to the list variable, you must not assign the result back to that variable, unlike with strings.\nThe append method modifies the list variable, and then returns None, so if you assign the method's result you overwrite the list variable.\nIf you don't assign back, the append call will mutate the list - changing the data inside the list without affecting the list variable.\n\n## Mutable Dataclasses\n\n```python example-dataclass\nfrom dataclasses import dataclass\n\n@dataclass\nclass Dog:\n    name: str\n    age: int\n\nbabbage = Dog(\"Babbage Bart\", 5)\nprint(babbage.name)\n# Mutably update the instance\nbabbage.name = \"Sir Babbage Bart\"\n# Value will have changed!\nprint(babbage.name)\n```\n\nDataclasses can also be mutated.\nAny time you assign to an instance's field, you are modifying the instance.\nIn the example shown, we create an instance of a `Dog` dataclass, and then later update its `name` field.\nAfterwards, the `name` field has a different value.\nIn this way, you can also see how fields are like variables.\n\n## Mutability and Parameters\n\n```python mutability-parameters\ndef add_x(a_list: list[str], a_str: str):\n    a_list.append(\"X\")\n    a_str = a_str + \" X\"\n\ncourses = [\"A\", \"B\", \"C\"]\nname = \"Ada\"\nadd_x(courses, name)\nprint(courses)\n# [\"A\", \"B\", \"C\", \"X\"]\nprint(name)\n# \"Ada\"\n```\n\nWe have seen mutability before when we learned about parameters of functions.\nLet's look at this function `add_x` that consumes a list and a string and adds the string value `\"X\"` to the end.\nWhen the function call is over, only the list has been changed.\nEven though we were using local versions of each variable, the mutability of the list type meant that the original list was changed.\nIf we wanted to change the `name` variable, we would have had to return the modified value and assign it back to the `name` variable.\n\n## Parameters in Stack/Heap Diagrams\n\n![A stack/heap diagram for a function call that involves a list being mutated.](bakery_structures_mutability_stack_heap.png)\n\nWe can visualize the difference in these two values by looking at a Stack/Heap diagram.\nNotice how there is only one list on the Heap because the same reference is shared between the `a_list` variable and the `letters` variable.\nHowever, the `name` and `a_str` have distinct values because strings are immutable.\n\n## Summary\n\n- In Python, all the primitive value types (string, integer, float, and Boolean) are immutable, which means that their intrinsic values cannot be changed for a given instance.\n- However, both lists and types created using dataclasses are mutable, which means that instances of those types can have their internal values changed.\n- When updating variables holding string variables, you must assign the newly computed value back to the same variable.\n- When updating lists, you call the `append` method and must _not_ assign the result to the list variable.\n- Instances of lists and dataclasses passed in as parameters can be mutated, which means that any global variables referencing those instances will also have those updates. However, this does not apply to immutable types like strings and integers.\n\n","ip_ranges":"","name":"4B3) Mutability Reading","on_change":"","on_eval":"","on_run":"","owner_id":1,"owner_id__email":"acbart@udel.edu","points":0,"public":true,"reviewed":false,"sample_submissions":[],"settings":"{\n  \"header\": \"Mutability\",\n  \"slides\": \"bakery_structures_mutability.pdf\",\n  \"youtube\": {\n    \"Bart\": \"Rvm-G-N5jaI\",\n    \"Amy\": \"Ty89jCYtGlw\"\n  },\n  \"summary\": \"This lesson shows how lists are different from other types because they are mutable (the variable's value can be changed, as opposed to taking on a new value).\",\n  \"small_layout\": true,\n  \"video\": {\n    \"Bart\": \"https://blockpy.cis.udel.edu/videos/bakery_structures_mutability-Bart.mp4\",\n    \"Amy\": \"https://blockpy.cis.udel.edu/videos/bakery_structures_mutability-Amy.mp4\"\n  }\n}","starting_code":"","subordinate":true,"tags":[],"type":"reading","url":"bakery_structures_mutability_read","version":8},"ip":"216.73.216.157","submission":{"_schema_version":3,"assignment_id":1053,"assignment_version":8,"attempts":0,"code":"","correct":false,"course_id":37,"date_created":"2026-05-20T14:01:50.298063+00:00","date_due":"","date_graded":"","date_locked":"","date_modified":"2026-05-20T14:01:50.298063+00:00","date_started":"","date_submitted":"","endpoint":"","extra_files":"","feedback":"","grading_status":"NotReady","id":2036921,"score":0.0,"submission_status":"Started","time_limit":"","url":"submission_url-34b15fe7-e680-4c5c-928d-d5dc4b7d13b3","user_id":2044668,"user_id__email":"","version":0},"success":true}
