This is probably one of the hardest things for new Python developers to understand and it becomes a real epiphany when they finally do. What you have there is no different to:
>>> x = [1]; print(x)
[1]
>>> y = x; print(x); print(y)
[1]
[1]
>>> y.append(2); print(x); print(y)
[1, 2]
[1, 2]
>>> z = x; z = 'nothing'; print(x); print(y); print(z)
[1, 2]
[1, 2]
nothing
The reason is does this is because, in Python, everything is an object and variables are simply bindings to objects.
So x = [1] creates the object [1] and binds the x variable to it.
When you then do y = x, that doesn't create a new object, it simply binds y to the already-existing object. That means x and y are now both bound to the same object so, when you do an operation that modifies the object, like x.append(), both x and y will be affected.
That doesn't occur with z = x; z = 'nothing' since the second step there is creating a new object and binding z to it, so that x/y and z are now bound to different things.
It also doesn't occur with either of:
z = x[:]
z = [item for item in x]
since both of those also create a new object (a copy of the original(1)), separating x and z.
The effect can be seen by examining the IDs of each variable (probably the only reason you should ever use id), with common prefix removed for readability:
>>> print(id(x)); print(id(y)); print(id(z))
49864
49864
53808
You can see that x and y are the same object, and z is different.
(1) Keep in mind you may need to do a deep copy if your data structures are sufficiently complex, such as (with comments added):
>>> x = [[1,2],[3,4]]; y = x; print(id(x)); print(id(y))
773190920 # same object
773190920
>>> y = x[:]; print(id(x)); print(id(y))
773190920 # different objects
832649864
>>> print(id(x[0])); print(id(y[0]))
773088840 # but the sub-objects are still identical.
773088840
a, to all thexattributes of your other classes,x = a.x...