0

I have the following problem in python:

I get a json from a list with 4 objects. I'm going to remove the last object from this list and assign it to 2 different variables. In the first variable I will add an object at the end of the list and in the second variable I will add another different object at the end of the list. The problem is that when I remove the last object from the first list, it is also removed from the second. How do I resolve this? I'm using the json below as an example.

test = [
    {'test': 'test1'
     },
    {'test': 'test2'
     },
    {'test': 'test3'
     },
    {'test': 'test4'
     }
]

block1 = test
block2 = test

print(block2)
block1.pop(3)
print(block2)

Output:

[{'test': 'test21'}, {'test': 'test2'}, {'test': 'test3'}, {'test': 'test4'}]
[{'test': 'test21'}, {'test': 'test2'}, {'test': 'test3'}]

Thanks.

juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • 4
    **There is only one list here**. There are three different variables referring to the same object, `test`, `block1`, and `block2`. – juanpa.arrivillaga Feb 09 '22 at 20:22
  • 2
    In this case, you could use `test.copy()`. Note, that will create a *shallow* copy, so the dict's inside your list aren't actually copied. If you need a deep copy, use `[d.copy() for d in test]`. Also, you should read this classic: https://nedbatchelder.com/text/names.html – juanpa.arrivillaga Feb 09 '22 at 20:23
  • [immutable vs mutable](https://stackoverflow.com/questions/8056130/immutable-vs-mutable-types) – JNevill Feb 09 '22 at 20:24
  • 1
    Also, as an aside, *there is no JSON anywhere here*. You have a list of dicts. JSON is a text-based serialization format, which isn't involved here – juanpa.arrivillaga Feb 09 '22 at 20:24
  • 2
    @JNevill while that is useful information, it is important to note, mutability doesn't change the semantics here at all, `block1 = test` will behave **exactly the same regardless of the type of object being referred to by `test`** – juanpa.arrivillaga Feb 09 '22 at 20:25
  • @juanpa.arrivillaga Is that I make a json.dumps after doing the treatments. But I understand what you mean. I had this problem because I come from vb. Thanks! – Bruno Souza Feb 09 '22 at 20:49
  • @juanpa.arrivillaga I disagree. Mutability is exactly the cause of the equals sign's changing behavior between an immutable and mutable object that is leading to OP's confusion. Not understanding the difference, means not understanding why the equal sign is acting differently. – JNevill Feb 09 '22 at 22:01
  • @JNevill **the behavior does not change at all**. The equal sign acts *exactly the same*. It assigns the object that the expression evaluates to on the right hand side to the name on the left. The type is *completely irrelevant*. E.g. `x = []; y = x; y = [1, 2, 3]; print(x)` will print `[]`, just like `x = 1; y = x; y = 99; print(x)` will print `1`. The semantics of assignment is *always* the same. – juanpa.arrivillaga Feb 09 '22 at 22:03
  • @juanpa.arrivillaga Your examples are outside the scope of mutability and this question. Instead: `x = []; y = x; y = y.append(1); print(x)` vs `x = 1; y = x; y = y + 1; print(x)` which shows the behavior that OP is seeing and is confused about, which is entirely due to the mutability of lists vs immutability of integer. In the first the equal sign means that the `y` gains the pointer/reference of `x` and in the second `y` gains the value of `x`. That's very different behavior under the hood. – JNevill Feb 10 '22 at 14:42
  • @JNevill **no** You are completely wrong. In both cases `y` "gains a reference to `x`". Of course, in the case of `int` objects, the type doesn't expose any mutator methods, but the *semantics of assignment are exactly the same*. This is crucial to understand. For **any object**, if you do `y = x` then `y is x`, i.e. `x = y; print(y is x)` will **always print `True`** regardless of the type! `int` objects are objects, Python doesn't have primitives, everything is an object – juanpa.arrivillaga Feb 10 '22 at 17:07
  • @JNevill So here, I'll prove it to you. First, `import ctypes`, then `x = 999` and `y = x`. Now, "immutability" is just a feature of the API, we can use implementation details to subvert that. `ctypes.cast(id(x), ctypes.POINTER(ctypes.c_int))[6] = 1337`. Now, `print(x, y)` should print `1337 1337`! Why? Because we *mutated the `int` object*, and since both `x` and `y` are referring to the same `int` object, we see that effect in both variables. – juanpa.arrivillaga Feb 10 '22 at 17:20

0 Answers0