Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need to copy class instances but not other object types in Python?

I'm a little confused about when I need to explicitly copy an object in Python in order to make changes without altering the original. The Python doc page doesn't have too much detail, and simply says that "assignment statements do not create copies".

Example 1:

>>> a = 4
>>> b = a
>>> b += 1
>>> print(b)
>>> print(a)

# Results are what you'd "expect" them to be:
5
4

Example 2:

>>> class Test():
>>>     def __init__(self, x):
>>>         self.x = x
>>> 
>>> A = Test(4)
>>> B = A
>>> B.x += 1
>>> print(B.x)
>>> print(A.x)

# Unexpected results because B isn't actually a copy of A:
5
5

Why do the two examples behave differently?

Edit: In order to get Example 2 to work, I basically did the following. I'm asking why this isn't necessary for Example 1:

>>> import copy
>>> A = Test(4)
>>> B = copy.copy(A)
>>> B.x += 1
>>> print(B.x)
>>> print(A.x)
like image 748
AdmiralWen Avatar asked Nov 21 '25 20:11

AdmiralWen


2 Answers

a = 4
b = a

..would mean "make b refer to whatever a refers to". That would be 4 in this case. Since integers are immutable, changing b by doing b += 1 would make it point to a different object

Check their ids:

a = 4
b = a

print(id(a)) # Same id
print(id(b)) # Same id

b = 123

print(id(b)) # Different id

Same thing happens with instances A and B when B is not a .copy().

id(object)

Return the “identity” of an object.


An interesting example with mutable objects:

l = [1, 2]
k = l

print(id(l)) # Same id
print(id(k)) # Same id

k.append(3)

print(id(k)) # Same id
print(l, k)  # Prints [1, 2, 3] [1, 2, 3]

append() modifies the object both k and l refer to. It doesn't assign k to a different object.

As mentioned by @blcckngth:

k = k + [3]

print(id(k)) # Different id ..
print(l, k)  # ..prints [1, 2] [1, 2, 3]

while k += [3] would result in reference to the same object.

like image 150
user Avatar answered Nov 23 '25 22:11

user


In your example 1, you write b += 1. That's the same thing as writing b = b + 1. That uses the = operator to assign a value to b. You're just changing the value that the name b refers to. In example 2, you're changing an attribute of the object that both names (A and B) refer to. They still both refer to the same object in memory, so changing the .x attribute of that object changes both B.x and A.x.

like image 22
KSFT Avatar answered Nov 23 '25 22:11

KSFT