Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Python's copy.copy() return a object not equal to the original?

Tags:

python

copy

In Python, if I copy a list or a dictionary, the copied instance is equal to the original:

>>> a = [1, 2, 3]
>>> b = copy.copy(a)
>>> a == b
True
>>> a = {"a":1, "b":2}
>>> b = copy.copy(a)
>>> a == b
True

But if I copy an object, the result is not equal to the original:

>>> class MyClass():
...     def __init__(self, name):
...             self._name= name
...
>>> a = MyClass('a')
>>> b = copy.copy(a)
>>> a == b
False

Why?

like image 699
NeoWang Avatar asked Jul 11 '15 05:07

NeoWang


1 Answers

Equality in Python for objects is checked by calling the __eq__() function.

Example:

>>> class CA:
...     def __eq__(self, other):
...             print("Equals")
...             return True
...
>>> c = CA()
>>> b = CA()
>>> c == b
Equals
True

That is because list equality is dependent on the elements and not the actual memory location (reference) where the list is stored, that is, they can be two different list references, but if they have the same elements in the same order, the lists are equal.

Example:

>>> l = [1,2]
>>> l1 = [1,2]
>>> id(l)
2830504
>>> id(l1)
2831864
>>> l == l1
True

But custom class, you have not overwritten __eq__(), hence it would call the __eq__() of the parent class, which is object, and that checks equality based on the reference.

And when you do copy.copy() it does shallow copying, that is, it creates a new instance the object with all its members (attributes, etc.) remaining the same. Hence, they are unequal (as they are different references/different instances).

If you want your MyClass to check equality based on self._name, you will have to overwrite the __eq__() function for that.

You can find more information about comparisons here.

like image 196
Anand S Kumar Avatar answered Oct 22 '22 10:10

Anand S Kumar