Skip to content

[Python] Use "copy" Module To Copy Object

Last Updated on 2021-10-05 by Clay

The most likely causes of programming error in Python is unexpected changes in the value fo List object. Many people have just encountered this problem, they may yell that Python is broken.

One of the simplest example is that the List object has been changed along with the assigned source:

# coding: utf-8


def main():
    # Init
    a = [[1, 1], [2, 2]]
    b = a

    # Append
    a.append([3, 3])

    # Print
    print('a:', a)
    print('b:', b)


if __name__ == '__main__':
    main()



Output:

a: [[1, 1], [2, 2], [3, 3]]
b: [[1, 1], [2, 2], [3, 3]]

It's weird, right? Obviously, the only variable that has added a new value is the variable a!

The reason for this is actually simple, because b is just a new variable name that shares the value of a. We can use the id() function to see:

# coding: utf-8


def main():
    # Init
    a = [[1, 1], [2, 2]]
    b = a

    # Append
    a.append([3, 3])

    # Print
    print('a id:', id(a))
    print('b id:', id(b))


if __name__ == '__main__':
    main()



Output:

a id: 140219101052168
b id: 140219101052168

You will find that a and b are really the same value, but the variable names are different.

But this is troublesome.

Usually we don’t want to use two variables with the same value but different names. We hope that b can "copy" the value of a. However, no matter how the value is increased or decreased in the future, both a and b are not related.

At this time, it is the turn of the copy module in Python to debut.


Shallow Copy & Deep Copy

Python's copy module is divided into two types: shallow copy and deep copy.


shallow copy

Shallow copy uses the copy() function to make the copied objects independent, that is, a and b are no longer relevant, and adding new values will not affect b.

# coding: utf-8
import copy


def main():
    # Init
    a = [[1, 1], [2, 2]]
    b = copy.copy(a)

    # Change
    a.append([3, 3])

    # Print
    print('a:', a)
    print('a id:', id(a))
    print('='*50)
    print('b:', b)
    print('b id:', id(b))


if __name__ == '__main__':
    main()



Output:

a: [[1, 1], [2, 2], [3, 3]]
a id: 140378660764744
==================================================
b: [[1, 1], [2, 2]]
b id: 140378660765000

But shallow copying is still different from deep copying. That is to say, although the addition and deletion of elements in the a variable will not affect b, if the element b in the a variable is directly changed, it will still affect b.

# coding: utf-8
import copy


def main():
    # Init
    a = [[1, 1], [2, 2]]
    b = copy.copy(a)

    # Change
    a[0][0] = 0

    # Print
    print('a:', a)
    print('a id:', id(a))
    print('='*50)
    print('b:', b)
    print('b id:', id(b))


if __name__ == '__main__':
    main()



Output:

a: [[0, 1], [2, 2]]
a id: 140223083543624
==================================================
b: [[0, 1], [2, 2]]
b id: 140223083543880

As you can see, the first element of [1, 1] has been changed. To prevent this from happening, you can only use deepcopy().


deep copy

Deep copy uses the deepcopy() function to completely separate the two variables a and b, which is a complete copy.

# coding: utf-8
import copy


def main():
    # Init
    a = [[1, 1], [2, 2]]
    b = copy.deepcopy(a)

    # Change
    a.append([3, 3])
    a[0][0] = 0

    # Print
    print('a:', a)
    print('a id:', id(a))
    print('='*50)
    print('b:', b)
    print('b id:', id(b))


if __name__ == '__main__':
    main()



Output:

a: [[0, 1], [2, 2], [3, 3]]
a id: 140719924018248
==================================================
b: [[1, 1], [2, 2]]
b id: 140719924018504

As you can see, even if the elements in a are modified this time, b will not be affected.


References


Read More

Tags:

Leave a Reply