<jupyter_start><jupyter_text>The copy module includes two functions, copy() and deepcopy(), for duplicating existing objects.  Shallow Copy<jupyter_code>import copy
import functools


@functools.total_ordering
class MyClass:

    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        return self.name == other.name

    def __gt__(self, other):
        return self.name > other.name


a = MyClass('a')
my_list = [a]
dup = copy.copy(my_list)

print('             my_list:', my_list)
print('                 dup:', dup)
print('      dup is my_list:', (dup is my_list))
print('      dup == my_list:', (dup == my_list))
print('dup[0] is my_list[0]:', (dup[0] is my_list[0]))
print('dup[0] == my_list[0]:', (dup[0] == my_list[0]))
print('id(dup[0])==id(dup[0])', (id(dup[0])==id(dup[0])))<jupyter_output>my_list: [<__main__.MyClass object at 0x108e036a0>]
                 dup: [<__main__.MyClass object at 0x108e036a0>]
      dup is my_list: False
      dup == my_list: True
dup[0] is my_list[0]: True
dup[0] == my_list[0]: True
id(dup[0])==id(dup[0]) True<jupyter_text>Deep Copy<jupyter_code>import copy
import functools


@functools.total_ordering
class MyClass:

    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        return self.name == other.name

    def __gt__(self, other):
        return self.name > other.name


a = MyClass('a')
my_list = [a]
dup = copy.deepcopy(my_list)

print('             my_list:', my_list)
print('                 dup:', dup)
print('      dup is my_list:', (dup is my_list))
print('      dup == my_list:', (dup == my_list))
print('dup[0] is my_list[0]:', (dup[0] is my_list[0]))
print('dup[0] == my_list[0]:', (dup[0] == my_list[0]))<jupyter_output>my_list: [<__main__.MyClass object at 0x108e10c88>]
                 dup: [<__main__.MyClass object at 0x108e10d30>]
      dup is my_list: False
      dup == my_list: True
dup[0] is my_list[0]: False
dup[0] == my_list[0]: True<jupyter_text>Customizing Copy Behavior<jupyter_code>import copy
import functools


@functools.total_ordering
class MyClass:

    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        return self.name == other.name

    def __gt__(self, other):
        return self.name > other.name

    def __copy__(self):
        print('__copy__()')
        return MyClass(self.name)

    def __deepcopy__(self, memo):
        print('__deepcopy__({})'.format(memo))
        return MyClass(copy.deepcopy(self.name, memo))


a = MyClass('a')

sc = copy.copy(a)
dc = copy.deepcopy(a)<jupyter_output>__copy__()
__deepcopy__({})<jupyter_text>Recursion in Deep Copy<jupyter_code>import copy


class Graph:

    def __init__(self, name, connections):
        self.name = name
        self.connections = connections

    def add_connection(self, other):
        self.connections.append(other)

    def __repr__(self):
        return 'Graph(name={}, id={})'.format(
            self.name, id(self))

    def __deepcopy__(self, memo):
        print('\nCalling __deepcopy__ for {!r}'.format(self))
        if self in memo:
            existing = memo.get(self)
            print('  Already copied to {!r}'.format(existing))
            return existing
        print('  Memo dictionary:')
        if memo:
            for k, v in memo.items():
                print('    {}: {}'.format(k, v))
        else:
            print('    (empty)')
        dup = Graph(copy.deepcopy(self.name, memo), [])
        print('  Copying to new object {}'.format(dup))
        memo[self] = dup
        for c in self.connections:
            dup.add_connection(copy.deepcopy(c, memo))
        return dup


root = Graph('root', [])
a = Graph('a', [root])
b = Graph('b', [a, root])
root.add_connection(a)
root.add_connection(b)

dup = copy.deepcopy(root)<jupyter_output>Calling __deepcopy__ for Graph(name=root, id=4443932488)
  Memo dictionary:
    (empty)
  Copying to new object Graph(name=root, id=4443878792)

Calling __deepcopy__ for Graph(name=a, id=4443932376)
  Memo dictionary:
    Graph(name=root, id=4443932488): Graph(name=root, id=4443878792)
  Copying to new object Graph(name=a, id=4443878904)

Calling __deepcopy__ for Graph(name=root, id=4443932488)
  Already copied to Graph(name=root, id=4443878792)

Calling __deepcopy__ for Graph(name=b, id=4441866080)
  Memo dictionary:
    Graph(name=root, id=4443932488): Graph(name=root, id=4443878792)
    Graph(name=a, id=4443932376): Graph(name=a, id=4443878904)
    4443932488: Graph(name=root, id=4443878792)
    4443904328: [Graph(name=root, id=4443932488), Graph(name=a, id=4443932376)]
    4443932376: Graph(name=a, id=4443878904)
  Copying to new object Graph(name=b, id=4443880696)
{'fraction_non_alphanumeric': 0.14458342166631333, 'fraction_numerical': 0.05766376934492262, 'mean_word_length': 3.3564173591874424, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '59786', 'license': 'MIT', 'n_tokens_mistral': 1864, 'n_tokens_neox': 1675, 'n_words': 389, 'path': 'Python-Standard-Library/DataStructures/copy.ipynb', 'repo_name': 'gaufung/CodeBase', 'size': '4717'}