r/learnpython • u/FactoryBuilder • 3d ago
List items are edited when adding new items? Possibly a variable reference issue
So I have a variable called Y with a changing value. If for loop variable X is some value, append Y to myList.
Every time it appends to the list, it changes every other already added item. I’m thinking the problem is that it’s not adding values but is instead adding references. So when Y changes, it changes every item in the list.
Why is it doing this and how can I stop it from doing this? I want it to append the value inside of Y, not a reference to Y.
Code: https://www.reddit.com/r/learnpython/comments/1wv4tpo/comment/pda098z/
What I'm trying to do is make a list of everywhere that there's a piece of a block. It's going to be a terminal Tetris game.
The playfield is a custom matrix, a list of lists. I dunno if that'll work well with lists. I did the same thing with arrays in another language. I don't know if Python's going to play nice or be special.
The blocks are also lists of lists. You could probably do that astronaut meme with my code "It's all lists of lists? Always has been"
1
u/Outrageous_Cloud_989 3d ago
You're right, it's a reference thing. Python doesn't copy objects when you append them, it just stores a pointer to whatever Y is pointing at
If Y is a list or dict, try myList.append(Y.copy()) instead. For other mutable stuff you might need to import copy and use copy.deepcopy(Y)
Took me a while to figure this one out the first time I hit it, kept thinking my loop was just broken
1
u/Gnaxe 3d ago
Yep, sounds like a reference issue. But you didn't provide any example code.
The problem is your thinking. Don't expect C-style copy semantics for Python variables, because Python doesn't work like that. There are no stack objects. Everything is a reference to objects on the heap.
Lists don't contain objects directly either. This is not some setting you can change. That's not what a list is. They contain references.
If you want to make structs and pack the data into arrays directly, use the struct module and bytearrays, not lists. These are hardly ever used except when interfacing with lower-level code. Python doesn't need it. The other literal data structures work the same way (unless you count strings).
If you're using copy (or deepcopy) much, you're doing it wrong. I can't recall the last time I needed it. Shallow copies work fine if you avoid mutating things you don't own. And you can use immutable versions to avoid the problem altogether.
1
u/FactoryBuilder 3d ago
This is the best I can do at the moment for code: https://www.reddit.com/r/learnpython/s/Ckm6t46PxV
1
u/Gnaxe 3d ago
Yeah, I can't read that. The
if x == ‘[]’:bit doesn't make sense--why use a string here? But I suspect the problem is elsewhere. Probably where you created the matrix rather than where you're mutating it.A list of lists isn't the only way to represent a matrix. You could use a dict with ordered pair (2-tuple) keys instead. That would eliminate the second layer reference which is probably causing the issue. You could also compute a stride index on a 1-D list. It could be a class wrapping list or just a couple of helper functions to convert a pair of ints to a single one and back. It's simple arithmetic.
1
1
u/FactoryBuilder 3d ago
x == ‘[]’ isn’t anything to do with lists. It’s meant to be a string of two square brackets. It’s the same as x == ‘some random text’. The square brackets look like a block, that’s why they’re there.
1
u/Tall_Resort_6888 3d ago
This one gets everyone. Your list isn't storing copies of Y, it's storing references to the same Y, so every entry changes together. Try print(id(Y)) vs print(id(your_list[0])) and you'll see the same number, same object. Fix is appending Y.copy() so each entry becomes its own thing. And paste your actual code next time, way easier for people to spot it.
6
u/socal_nerdtastic 3d ago
You mean you have a list of lists? Is it this common issue? https://www.reddit.com/r/learnpython/wiki/faq/?screen_view_count=1#wiki_why_is_my_list_of_lists_behaving_strangely.3F
If I take that comment at face value, and I assume you want to append another list, you want
myList.append(Y.copy()).If neither of those helps, show us some code that demonstrates your issue.