Python Changing List in Dictionary Changes All Lists (no other solutions working)

I have spent the past 3 hours reading posts here explaining exactly the problem I am having, but none of the solutions are working.

These posts did NOT work:

Changing one list unexpectedly changes another, too

Changing One dict value changes all values

I have a python module where I have have a specific shape of 2D array I need to initialize the entries in a dictionary with. Here is how I have done it:

empty = []
for x in range(2):
    empty.append([])
    for y in range(2):
        empty[x].append(False)

status = {k:[] for k in ["a", "b", "c"]}

status["a"] = list(empty)
status["b"] = list(empty)
status["c"] = list(empty)

print(status)
status["a"][0][0] = True
print(status)

(Shape of list simplified for example)

This prints:

{'a': [[False, False], [False, False]], 'b': [[False, False], [False, False]], 'c': [[False, False], [False, False]]}
{'a': [[True, False], [False, False]], 'b': [[True, False], [False, False]], 'c': [[True, False], [False, False]]}

As you can see, setting one of the lists values changes all of the lists. I do not want this, I want them to be separate lists (in one dictionary) with different values. Initially, I thought I had done the old newlist = oldlist blunder where I set newlist to the same object as oldlist, but nope. As you can see in my code, I am making separate lists using newlist = list(oldlist). I have also tried newlist = oldlist[:], newlist = oldlist.copy(), etc etc.

What am I missing? Thank you so much for taking the time to look this question over, I appreciate any input.

from copy import deepcopy
empty = []
for x in range(2):
    empty.append([])
    for y in range(2):
        empty[x].append(False)

status = {k:[] for k in ["a", "b", "c"]}

status["a"] = deepcopy(empty)
status["b"] = deepcopy(empty)
status["c"] = deepcopy(empty)

print(status)
status["a"][0][0] = True
print(status)

you were close with the copy, but you actually neeed a deepcopy

Python points both lists in vec = v to the same spot of memory. To copy a list use vec=v[:]. This might all seem counter-intuitive. Why not make  7 How to generate dynamic function name and call it using user input in Python Sep 17 '18 6 Search through multiple fields in Django Oct 26 '16 5 Python Changing List in Dictionary Changes All Lists (no other solutions working) Oct 4 '18

As I said earlier, list(empty) does create a new list, but the inner lists of that new list are just references to the same list objects in empty.

You can use deepcopy, but I think it's simpler just to build new lists when you need them. The deepcopy function jumps through various hoops that are required to copy arbitrarily deep nested objects that can contain anything. But why bother going through all that stuff when you have a structure that's simple to just build from scratch?

Using a list comprehension, your code can be written like this:

status["a"] = [[False] * 2 for _ in range(2)]
status["b"] = [[False] * 2 for _ in range(2)]
#etc

It's safe to do [False] * 2 for the innermost lists: it's always safe to share immutable objects (booleans, integers, strings, etc). The problem only arises when you unexpectedly share a mutatable object and you mutate its value instead of replacing it with a new object.

To avoid re-writing that list comp, you can use a function to build the lists for you. Eg,

def empty(rows, columns):
    return [[False] * columns for _ in range(rows)]

status = {key: empty(2, 2) for key in 'abc'}
print(status)
status["a"][0][0] = True
print(status)

output

{'a': [[False, False], [False, False]], 'b': [[False, False], [False, False]], 'c': [[False, False], [False, False]]}
{'a': [[True, False], [False, False]], 'b': [[False, False], [False, False]], 'c': [[False, False], [False, False]]}

In this beginner Python tutorial, we'll take a look at mutable and immutable data of the global variables number_1 and number_2 did not change, even though we Thus, the variable number_1 can have one value (5) globally, and a different If all of them are changing the lists and dictionaries they're working on, it can  Python Resize List: Slice and Append Resize lists with slice syntax and the append method. Reduce and increase the size of lists.

You can see that the first element of your empty list is shared across all the values in your dictionary:

>>> id(empty[0]) == id(status['a'][0]) == id(status['b'][0]) == id(status['c'][0])
True

They each share the same memory location. The same is also true for the second item in the empty list, id(empty[1]) == id(status['a'][1]) == ...

The reason for this is your assignment of your empty list to each value. You can either perform a deep copy this empty, nested list, or else use a list comprehension to generate new ones for each key in your dictionary. This list comprehension for the empty list creation is itself done within a dictionary comprehension to generate your status variable for all the required keys.

empty_rows = 2
empty_cols = 2
keys = ['a', 'b', 'c']
status = {k: [[False] * empty_cols 
              for _ in range(empty_rows)] 
          for k in keys}

# Example usage:
status['a'][0][0] = True
>>> status
{'a': [[True, False], [False, False]],
 'b': [[False, False], [False, False]],
 'c': [[False, False], [False, False]]}

Now you can change any element without it affecting the others.

But what if you need to store a long list of information, which doesn't change over time? For these three problems, Python uses three different solutions - Tuples, lists, as a tuple, EXCEPT that all the values are put between square brackets, not #Remember - this is how 'if' statements work - #they run if something is true​  Dictionary in Python is an unordered collection of data values, used to store data values like a map, which unlike other Data Types that hold only single value as an element, Dictionary holds key : value pair. keys () method in Python Dictionary, returns a view object that displays a list of all the keys in the dictionary.

I think what you need is a deep copy, see documentation of copy.deepcopy()

import copy
empty = []
for x in range(2):
    empty.append([])
    for y in range(2):
        empty[x].append(False)

status = {k:[] for k in ["a", "b", "c"]}

status["a"] = copy.deepcopy(empty)
status["b"] = copy.deepcopy(empty) 
status["c"] = copy.deepcopy(empty)
status['a'][0][0] = True
print(status)

Sometimes, a list is not exactly what you questions and their answers. This operation allows you to glue together all strings in your list together and return You can change a list to a tuple in Python by A dictionary works with keys and values,  The index numbers for this list range from 0 - 4, as shown in the table above. So to call any of the items individually, we would refer to the index numbers like this: sea_creatures[0] = 'shark' sea_creatures[1] = 'cuttlefish' sea_creatures[2] = 'squid' sea_creatures[3] = 'mantis shrimp' sea_creatures[4] = 'anemone'.

Extend the list by appending all the items in the given list. remove or sort that only modify the list have no return value printed – they from the beginning of a list is slow (because all of the other elements have to be shifted by one). Common applications are to make new lists where each element is the  18 Most Common Python List Questions Discover how to create a list in Python, select list elements, the difference between append() and extend(), why to use NumPy and much more. The post will offer simple solutions, easy-to-follow and straightforward explanations and some tips and tricks that you can practice on the spot with the help of some

Have you ever wanted to combine two or more dictionaries in Python? Before we can discuss solutions, we need to clearly define our problem. defaults and user should not change during the creation of context In Python 2 we actually don't need the list conversions, but we're working in Python 3  Problem Solving with Algorithms and Data Structures, Release 3.0 Figure 1.1: Procedural Abstraction must know the details of how operating systems work, how network protocols are configured, and how to code various scripts that control function. They must be able to control the low-level details that a user simply assumes.

A Complete Introduction to the Python Language Mark Summerfield The example we will use is the solution to one of the exercises given at the end of that either all of a set of changes is applied to a list, set, or dictionary—or none of them We will need to test three different kinds of data type: lists, sets, and dictionaries. Hi. I have an attribute table with many fields where I have to change the field name. Most of the field names start with All_txt_ . As I found out in the Data Management Forum, there is no way to automatically change all these field names in ArcGIS with a tool.

Comments
  • I guess you've seen stackoverflow.com/questions/240178/… ?list(empty) does create a new list, but the inner lists of that new list are just references to the same list objects in empty.
  • Mandatory reading: nedbatchelder.com/text/names.html
  • Exactly what I needed! It works! I didn't realize the INNER lists were the same object, too!
  • Totally agree. I believe deepcopy is overkill for this situation.
  • +1 for the id() function. I would recommend to the OP to really play around with it and understand what's going on
  • hey, it is not different, I was typing the answer, got busy with other things, and when submitted the previous answers were already there ... (perhaps, the only thing is that I had added a reference to the python docs)