15 | Python object comparison, copy

table of Contents

 

1. Review

2. Deep copy

3. Summary

4. Thinking


1. Review

In the previous lessons, I have learned many examples of python object comparison and copying

if a == b:
    ...

The l2 here is the copy of l1.

l1 = [1, 2, 3]
l2 = list(l1)

Is l2 a shallow copy or a deep copy of l1?

Does a == b compare the values ​​of two objects for equality, or does the two objects are exactly equal?

1.“==”VS“is”

== and is are two commonly used methods of object comparison in python. The "==" operator compares whether the values ​​between objects are equal, eg

a == b

The is operator comparison is whether the identities of the objects are equal, that is, whether they are the same object and whether they point to the same memory address.

In python, the identity of each object is obtained through the function id(object). Therefore, the'is' operator is equivalent to comparing whether the IDs between objects are equal. The following example:

a = 10
b = 10

a == b
True

id(a)
4427562448

id(b)
4427562448

a is b
True

Python will create a memory for 10, and then the variables a and b point to this memory area at the same time, that is, both a and b point to the variable 10. Therefore, the values ​​of a and b are equal, and the id is also equal, a==b, and Both a and b return True.

But it should be noted that for integer numbers, the above conclusion that a is b is True is only suitable for numbers in the range of -5 to 255.

a = 257
b = 257

a == b
True

id(a)
4473417552

id(b)
4473417584

a is b
False
if a is None:
      ...

if a is not None:
      ...

The comparison operator'is' is usually better than "==". Because the is operator cannot be overloaded, so python does not need to look for it. Is there any other overloaded comparison operator in the program and call it to perform the comparison operation? The character'is' just compares the IDs of two variables.

But the "==" operator is different. Executing a == b is equivalent to executing a.__eq__(b), and most data types in python will overload the __eq__ function, and its internal processing will be more complicated. For a list, the __eq__ function will traverse the elements in the list and compare their order and whether their values ​​are equal.

For immutable variables, if we compare with'==' or'is' before, will the result remain unchanged?

t1 = (1, 2, [3, 4])
t2 = (1, 2, [3, 4])
t1 == t2
True

t1[-1].append(5)
t1 == t2
False

The answer is no, we know that tuples are immutable, but tuples can be nested, the elements in it can be list types, and lists are mutable, so if we modify a variable element in the tuple , Then the tuple itself has also changed. The result of using the'is' or'==' operator before may not be applicable.

2. Shallow copy and deep copy

A common shallow copy method is to use the constructor of the data type itself, such as:

l1 = [1, 2, 3]
l2 = list(l1)

l2
[1, 2, 3]

l1 == l2
True

l1 is l2
False

s1 = set([1, 2, 3])
s2 = set(s1)

s2
{1, 2, 3}

s1 == s2
True

s1 is s2
False

Here l2 is the shallow copy of l1, and s2 is the shallow copy of s1. For variable sequences, we can also use the slice operator ":" to complete the shallow copy, as follows

l1 = [1, 2, 3]
l2 = l1[:]

l1 == l2
True

l1 is l2
False

Of course, python also provides a corresponding function copy.copy(), which is suitable for any data type:

import copy
l1 = [1, 2, 3]
l2 = copy.copy(l1)

However, it should be noted that for tuples, using tuple() or the slice operator':' will not create a shallow copy, on the contrary, it will return a reference to the same tuple

t1 = (1, 2, 3)
t2 = tuple(t1)

t1 == t2
True

t1 is t2
True

Here, the tuple (1,2,3) is created only once, and t1 and t2 point to this tuple at the same time. Shallow copy is to reallocate a piece of memory, and create a new reference to the element in the object is a reference to the sub-object in the original object. Therefore, if the elements in the original object remain the same, it does not matter, but if it changes, the shallow copy will do. Side effects, so pay attention.

l1 = [[1, 2], (30, 40)]
l2 = list(l1)
l1.append(100)
l1[0].append(3)

l1
[[1, 2, 3], (30, 40), 100]

l2
[[1, 2, 3], (30, 40)]

l1[1] += (50, 60)
l1
[[1, 2, 3], (30, 40, 50, 60), 100]

l2
[[1, 2, 3], (30, 40)]

First initialize a list l1, the elements in it are a list and a tuple, and then perform a shallow copy of l1 and assign l2. Because the elements in the shallow copy are references to the original elements, the elements in l2 and l1 point to the same List and tuple objects.

2. Deep copy

copy.deepcopy() in python to achieve deep copy of objects

import copy
l1 = [[1, 2], (30, 40)]
l2 = copy.deepcopy(l1)
l1.append(100)
l1[0].append(3)

l1
[[1, 2, 3], (30, 40), 100]

l2 
[[1, 2], (30, 40)]

No matter how l1 changes, l2 will not change. Is independent.

However, deep copy is not perfect. If there is a reference to itself in the copied object, it will fall into an infinite loop.

import copy
x = [1]
x.append(x)

x
[1, [...]]

y = copy.deepcopy(x)
y
[1, [...]]

3. Summary

4. Thinking

Run the code to test your ideas

import copy
x = [1]
x.append(x)

y = copy.deepcopy(x)

# 以下命令的输出是?
x == y

Shallow copy, immutable, immutable, mutable, still mutable
Deep copy, immutable

Guess you like

Origin blog.csdn.net/yanyiting666/article/details/92800810