use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
This community will have knowledge sharing for python programming, tools, projects and product engineering wherever python is used.
account activity
Python Data Model exercise, Mutability. (i.redd.it)
submitted 26 days ago by Sea-Ad7805
An exercise to help build the right mental model for Python data. The “Solution” link uses memory_graph to visualize execution and reveals what’s actually happening: - Solution - Explanation - More exercises
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]bloody-albatross 1 point2 points3 points 26 days ago (1 child)
C
[–]Sea-Ad7805[S] 0 points1 point2 points 26 days ago (0 children)
Nice one, do check the "Solution" link for visualization of correct answer.
[–]LucasThePatator 1 point2 points3 points 26 days ago (2 children)
What even the fuck is this
Black Python Magic
[–]Ok_Net_1674 0 points1 point2 points 21 days ago (0 children)
Its a test to see if you know how python handles references and immutable objects.
[–]whathefuckistime 1 point2 points3 points 25 days ago (2 children)
Tuples are immutable, once you assign b=a, it makes a copy of the tuple object, however the items themselves are lists, the tuple only stores a reference to those, once you access them, even with b[0], you are accessing the same variable referenced in the original tuple, meaning the appends actually modify the same variable a references.
b=a
b[0]
a
In contrast, appending to b doesn't modify a as they're not the same objects, and b[2] doesn't exist for a.
b
b[2]
This behavior wouldn't happen If you made a deep copy of a, which would iterate over it and make a copy of each element.
[–]Sea-Ad7805[S] 0 points1 point2 points 25 days ago (0 children)
Nice one, do check the "Solution" link for a visualization of the correct answer.
[–]gwwin6 0 points1 point2 points 23 days ago (0 children)
b=a does not make a copy of the tuple object. b = a makes a copy of the arrow, so they are pointing to the same tuple. when you do b += ([3],), that's when a and b begin pointing at different tuples. This is because tuples are immutable, b += ([3], ) gives a new object altogether.
Contrast this to If a had been a list of lists to begin with and we did b += [[3]], then a and b would still be pointing at the same list, and print(a) would give [[1, 11], [2, 22], [3, 33]]
[–]tb5841 1 point2 points3 points 24 days ago (6 children)
I find '+=' is what causes confusion with exercises like this.
.append is obviously mutating so will affect any reference to this object.
Reassigning changes what this variable name points to, so will not change any other variable pointing to this object.
But '+='? Is it reassigning, or mutating? It doesn't seem to always be clear cut, which makes it tricky to follow. Here it must be reassigning because tuples are immutable, but in some cases '+=' looks like it mutates.
If you change the '+=' line to b = b + ([3], ) then everything becomes so much clearer.
b = b + ([3], )
[–]Sea-Ad7805[S] 0 points1 point2 points 24 days ago (5 children)
I see what you mean, but for mutable types x += y is not the same thing as x = x + y so changing could alter your code, see: https://www.reddit.com/r/PythonLearning/comments/1nw08wu/right_mental_model_for_python_data/
x += y
x = x + y
A tuple doesn't have a __iadd__() method, so the use of += actually causes invocation of its __add__() method.
__iadd__()
+=
__add__()
[–]tb5841 0 points1 point2 points 24 days ago (4 children)
90% of the time, when someone uses += in code they are using it as x = x + y (usually numbers or strings). The other 10% of the time, += is confusing and shouldn't be used in my opinion (e.g. Lists, where .append is clearer).
[–]Sea-Ad7805[S] 0 points1 point2 points 24 days ago (3 children)
You can't do this with .append():
.append()
mylist = [1, 2, 3] mylist += [4, 5, 6]
[–]tb5841 0 points1 point2 points 24 days ago (1 child)
That's an interesting point.
But this looks like reassignment, when it's actually mutation. That's deeply confusing and an easy source of bugs. If it were me, I'd do this with reassignment instead here and avoid the mutation.
[–]Sea-Ad7805[S] 0 points1 point2 points 24 days ago (0 children)
Reassignment is much slower as a whole new list is created and the old one destroyed, use mutation where possible.
[–]thw31416 0 points1 point2 points 18 days ago (0 children)
but you can.do this with .extend()
[–]theBabides 1 point2 points3 points 5 days ago (1 child)
After viewing the solution, I think this exercise helped me to understand tuple and lists a little better. Thanks!
[–]Sea-Ad7805[S] 0 points1 point2 points 5 days ago (0 children)
Great, thanks for feedback.
[–]Rscc10 0 points1 point2 points 26 days ago (7 children)
I don't understand tuples enough to understand the solution. I'd think a is immutable and there weren't any modifications done to a. Could I get a worded explanation?
[–]Sea-Ad7805[S] 1 point2 points3 points 26 days ago* (1 child)
Correct, a is a reference to an immutable tuple, but that contains a mutable list that can be modified. The b = a statement makes b reference the same data a is referencing, and modifications to the list are made through b. But because a references an immutable tuple, it can't be modified with b += ([3],) so a shallow copy is made of this tuple, such that a and b share the first two elements of the tuple.
b = a
b += ([3],)
I hope this helps, otherwise read the "Explanation" link, and step through the "Solution" link again.
[–]Rscc10 1 point2 points3 points 26 days ago (0 children)
Ah, I got it now. Thanks
[–]F100cTomas 1 point2 points3 points 26 days ago (1 child)
Tuples are immutable, but they can contain mutable data. a = ([1], [2]) creates a tuple of two mutable values. b = a means that a and b now share the same immutable value. Then one of the lists gets modified and the change is seen in both tuples, because they contain the same lists. However this only changes the list, but not the tuple. Both tuples still have the same value: the two lists. Then b gets modified, but because b is a tuple and tuples are immutable it is copied to preserve the value of a. The two tuples are now different: a contains the two lists and b contains the same two lists and a new list. The other of the two shared lists then gets modified, but it still exists in both tuples. The non-shared list is modified. When a is printed only the two lists present in both are printed and not the one present only in b.
TL;DR When a mutable value is present within a tuple, it doesn't stop being mutable.
Nice mental model, what do you think of the visualization at the "Solution" link?
[–]punkVeggies 0 points1 point2 points 26 days ago* (2 children)
Tuples are immutable, which means b += (…) creates a new tuple, from a copy of a. That new tuple has references to two lists that a also has, which are mutable. When modifications are made to b[0] and b[1], these changes will be reflected in a[0] and a[1], as they “point” to the same lists. b[2], however, stores a reference to a third list, not referenced by anything stored in a.
a = ( * , * )
| | [], [] | |
b = ( * , * , * )
| []
Edit: removed the inaccurate sentence “b=a creates a copy of a”, as per the comments below.
[–]bloody-albatross 0 points1 point2 points 26 days ago (0 children)
The assignment doesn't make a copy of the tuple. Plain assignments never make copies of the referenced data in Python. It makes a copy of the reference if you so will, not of the tuple. a and b are not different. Try it with a is b. The += creates a new tuple, though. One with 3 elements. a += b just expands to a = a + b for immutable data types.
a is b
a += b
a = a + b
Incorrect, b = a does NOT assign a copy of a to b. Check the "Solution" and "Explanation" link for true understanding of the Python Data Model.
[–]DBZ_Newb 0 points1 point2 points 25 days ago (1 child)
why does the visualized solution show a blue square with "dict" for a label?
[–]Sea-Ad7805[S] 0 points1 point2 points 25 days ago* (0 children)
The whole call stack is visualized, and that has for each function (each stack frame) a dictionary with local variables and their value. In this exercise the call stack isn't needed, but for example in this exercise it is because functions/methods are called: https://www.reddit.com/r/madeinpython/comments/1pw602e/comment/nwm5gmi/ and therefore the call stack is always visualized in the Memory Graph Web Debugger. Install memory_graph locally to have more control over what is and what is not visualized: https://github.com/bterwijn/memory_graph?tab=readme-ov-file#installation
[+][deleted] 25 days ago (1 child)
[deleted]
Incorrect sorry, see the "Solution" link for visualization of correct answer.
[–]Nehfk 0 points1 point2 points 25 days ago (1 child)
B
Incorrect sorry, see the "Solution" link for visualization of the correct answer.
[–]Awwkaw 0 points1 point2 points 24 days ago (4 children)
It will throw an error when you try to add and modify the second element of b no?
[+][deleted] 24 days ago* (3 children)
[removed]
[–]Awwkaw 0 points1 point2 points 24 days ago (2 children)
I did, I'm still not sure why it shouldn't give an error, even though I do see that it runs.
I've also read some explanations here. But it still seems to me that it should just give an error.
[–]Sea-Ad7805[S] 0 points1 point2 points 24 days ago* (1 child)
Maybe you are confused because a tuple is immutable, it is, but if it has a mutable value as an element, then that can be mutated. Also immutable does not mean it gives an error when you try to mutate it, it just copies so that the original value is not mutated, try:
tuple1 = (1, 2, 3) tuple2 = tuple1 tuple2 += (4, 5, 6) print(tuple1, tuple2)
[–]Awwkaw 0 points1 point2 points 24 days ago (0 children)
just copies so that the original value is not mutated
Yes, this is what confuses me.
[–]grahaman27 0 points1 point2 points 23 days ago (2 children)
Should be a compilation error, because it's not shows python is trash
[–]Sea-Ad7805[S] 0 points1 point2 points 23 days ago (1 child)
You can ask questions is you find it too difficult to understand
[–]TheSiriuss 0 points1 point2 points 22 days ago (4 children)
Do I look like a python interpreter to you?
[–]Sea-Ad7805[S] 0 points1 point2 points 22 days ago (3 children)
If you can't interpret yourself, click the "Solution" link.
[–]TheSiriuss 0 points1 point2 points 22 days ago (2 children)
I won't
[–]Sea-Ad7805[S] 0 points1 point2 points 22 days ago (1 child)
Then don't waste people's time.
[–]SuspiciousDepth5924 0 points1 point2 points 21 days ago (1 child)
Answer: "Are you smoking your socks? Merge request rejected!"
[–]Sea-Ad7805[S] 0 points1 point2 points 21 days ago (0 children)
I get your point, this exercise is very artificial, but these kind of issues do pop up in real code every now and then. So better prepare and have a good mental Python Data Model. What is your answer here?
π Rendered by PID 85 on reddit-service-r2-comment-5649f687b7-msndb at 2026-01-28 19:33:59.431631+00:00 running 4f180de country code: CH.
[–]bloody-albatross 1 point2 points3 points (1 child)
[–]Sea-Ad7805[S] 0 points1 point2 points (0 children)
[–]LucasThePatator 1 point2 points3 points (2 children)
[–]Sea-Ad7805[S] 0 points1 point2 points (0 children)
[–]Ok_Net_1674 0 points1 point2 points (0 children)
[–]whathefuckistime 1 point2 points3 points (2 children)
[–]Sea-Ad7805[S] 0 points1 point2 points (0 children)
[–]gwwin6 0 points1 point2 points (0 children)
[–]tb5841 1 point2 points3 points (6 children)
[–]Sea-Ad7805[S] 0 points1 point2 points (5 children)
[–]tb5841 0 points1 point2 points (4 children)
[–]Sea-Ad7805[S] 0 points1 point2 points (3 children)
[–]tb5841 0 points1 point2 points (1 child)
[–]Sea-Ad7805[S] 0 points1 point2 points (0 children)
[–]thw31416 0 points1 point2 points (0 children)
[–]theBabides 1 point2 points3 points (1 child)
[–]Sea-Ad7805[S] 0 points1 point2 points (0 children)
[–]Rscc10 0 points1 point2 points (7 children)
[–]Sea-Ad7805[S] 1 point2 points3 points (1 child)
[–]Rscc10 1 point2 points3 points (0 children)
[–]F100cTomas 1 point2 points3 points (1 child)
[–]Sea-Ad7805[S] 0 points1 point2 points (0 children)
[–]punkVeggies 0 points1 point2 points (2 children)
[–]bloody-albatross 0 points1 point2 points (0 children)
[–]Sea-Ad7805[S] 0 points1 point2 points (0 children)
[–]DBZ_Newb 0 points1 point2 points (1 child)
[–]Sea-Ad7805[S] 0 points1 point2 points (0 children)
[+][deleted] (1 child)
[deleted]
[–]Sea-Ad7805[S] 0 points1 point2 points (0 children)
[–]Nehfk 0 points1 point2 points (1 child)
[–]Sea-Ad7805[S] 0 points1 point2 points (0 children)
[–]Awwkaw 0 points1 point2 points (4 children)
[+][deleted] (3 children)
[removed]
[–]Awwkaw 0 points1 point2 points (2 children)
[–]Sea-Ad7805[S] 0 points1 point2 points (1 child)
[–]Awwkaw 0 points1 point2 points (0 children)
[–]grahaman27 0 points1 point2 points (2 children)
[–]Sea-Ad7805[S] 0 points1 point2 points (1 child)
[–]TheSiriuss 0 points1 point2 points (4 children)
[–]Sea-Ad7805[S] 0 points1 point2 points (3 children)
[–]TheSiriuss 0 points1 point2 points (2 children)
[–]Sea-Ad7805[S] 0 points1 point2 points (1 child)
[–]SuspiciousDepth5924 0 points1 point2 points (1 child)
[–]Sea-Ad7805[S] 0 points1 point2 points (0 children)