Parfois, vous souhaiterez une copie complète d’un objet, d’autres fois, vous souhaiterez qu’il utilise des références. Voyez les différences en action.

Python propose plusieurs approches efficaces pour gérer les données. Comprendre les concepts de copie superficielle et profonde est crucial lorsque vous travaillez avec des structures de données telles que des listes imbriquées, des dictionnaires ou des objets personnalisés.

Les copies superficielles et profondes vous permettent de créer des répliques de structures de données, mais elles agissent différemment en ce qui concerne les données imbriquées.

Utilisation de la copie superficielle

La copie superficielle fonctionne en créant une copie de la structure de niveau supérieur de l'objet d'origine. Cela signifie que si l'objet d'origine contient des objets imbriqués, la copie fera référence aux mêmes objets imbriqués que l'original. En d’autres termes, faire une copie superficielle d’un objet duplique sa structure la plus externe, et non les objets imbriqués qu’il peut contenir.

Pour effectuer une copie superficielle en Python, vous pouvez utiliser le module de copie copie() fonction ou le .copie() méthode sur l’objet.

Prenons un exemple de travailler avec une liste ou un dictionnaire en Python.

import copy

main_list = [29, 49, ["Q", "R"]]
shallow_copy = copy.copy(main_list)

# Modify the nested list
shallow_copy[2][0] = 99
main_list[2][1] = 100

print(f"The main list: {main_list}")
print(f"The shallow copy list: {shallow_copy}")

Dans le code ci-dessus, le liste_main La variable contient une liste contenant des entiers et une liste interne (objet imbriqué) contenant des lettres. La fonction de copie crée une copie du liste_main que le code stocke dans une autre variable, copie superficielle.

Toute modification que vous apportez au copie superficielle la liste imbriquée affectera également directement celle de la liste_main et vice versa. Ces changements montrent que la liste imbriquée ou interne des copie superficielle est juste une référence à celle du liste_main, en appliquant les modifications dans liste_main aussi.

Pendant ce temps, toute modification apportée aux éléments externes (les entiers) dans l'un ou l'autre copie superficielle ou liste_main n'affectera que cette instance. Ces éléments externes sont des valeurs indépendantes à part entière, et non de simples références.

import copy

main_list = [29, 49, ["Q", "R"]]
shallow_copy = copy.copy(main_list)

# Modify the outer items
shallow_copy[0] = "M"
main_list[1] = "N"

print(f"The main list: {main_list}")
print(f"The shallow copy list: {shallow_copy}")

Le résultat démontre que les éléments externes des deux listes sont indépendants les uns des autres :

La même idée s'applique lorsque vous travaillez avec des dictionnaires.

dict1 = {'ten': 10, 'twenty': 20, 'double':{'thirty': 30, 'sixty': 60}}
dict2 = dict1.copy()

# Modify inner and outer elements
dict1['double']['thirty'] = 30.00
dict1['ten'] = 10.00

print(f"The main dictionary, {dict1}")
print(f"The shallow copy dictionary, {dict2}")

Modifications apportées au dictionnaire imbriqué de dict1 affecter les deux dict1 et dict2. Dans le même temps, des modifications sont apportées aux éléments extérieurs de dict1 n’affecte que lui.

Utiliser la copie approfondie

Au lieu de référencer les objets imbriqués de la copie originale, une copie complète crée une copie entièrement distincte de l'objet original et de ses objets imbriqués. La modification de la copie complète n'affectera pas l'objet d'origine et vice versa; ce sont des valeurs véritablement distinctes.

Pour faire une copie complète en Python, utilisez le copie profonde() fonction du module de copie.

Prenons un exemple de travail avec une liste.

import copy

main_list = [200, 300, ["I", "J"]]
deep_copy = copy.deepcopy(main_list)

# Modify the inner and outer list
deep_copy[2][0] = "K"
main_list[0] = 500

print(f"The main list: {main_list}")
print(f"The deep copy list: {deep_copy}")

Ici, le code effectue une copie complète de liste_main, créant une copie indépendante nommée copie_profonde.

Lorsque vous modifiez la liste imbriquée ou les éléments externes dans le copie_profonde, vos modifications n'affectent pas la liste d'origine, et vice versa. Cela démontre que la liste imbriquée ou les éléments externes ne sont pas partagés entre les deux copies.

Travailler avec des objets personnalisés

Vous pouvez créer un objet personnalisé en définir une classe Python et créer une instance de la classe.

Voici un exemple de création d'un objet simple à partir d'un Livre classe:

classBook:
def__init__(self, title, authors, price):
self.title = title
self.authors = authors
self.price = price

def__str__(self):
returnf"Book(title='{self.title}', author='{self.authors}', \
price='{self.price}')"

Maintenant, faites à la fois une copie superficielle et une copie complète d'une instance de ceci Livre classe en utilisant le copie module.

import copy

# Create a Book object
book1 = Book("How to MakeUseOf Shallow Copy", \
["Bobby Jack", "Princewill Inyang"], 1000)

# Make a shallow copy
book2 = copy.copy(book1)

# Modify the original object
book1.authors.append("Yuvraj Chandra")
book1.price = 50

# Check the objects
print(book1)
print(book2)

Comme vous pouvez le voir, la copie superficielle (livre2) est un nouvel objet, mais il fait référence au même objet interne (liste d'auteurs) que l'objet d'origine (livre1). Par conséquent, une modification des auteurs de l’objet d’origine affecte les deux instances (book1 et book2), tandis qu’une modification de l’élément externe (prix) n'affecte que l'objet d'origine (livre1).

D'un autre côté, réaliser une copie complète crée une copie indépendante de l'objet original, y compris des copies de tous les objets qu'il contient.

# Create a Book object
book1 = Book("Why MakeUseOf Deep Copy?", \
["Bobby Jack", "Yuvraj Chandra"], 5000)

# Make a deep copy
book2 = copy.deepcopy(book1)

# Modify the original object
book1.authors.append("Princewill Inyang")
book1.price = 60

# Check the objects
print(book1)
print(book2)

Dans ce cas, la copie profonde (livre2) est un objet complètement indépendant, et modifiant l'objet d'origine (livre1) ne l'affecte pas.

Utilisations pour la copie superficielle et la copie approfondie

Il est essentiel de comprendre la copie approfondie et superficielle afin de pouvoir sélectionner l'approche appropriée pour manipuler les données. Voici quelques scénarios dans lesquels chaque méthode est applicable :

  • Utilisez une copie superficielle si vous souhaitez répliquer un objet complexe sans générer de nouvelles instances de ses objets imbriqués. Cette approche est plus efficace en termes de mémoire et plus rapide que la copie complète, car elle ne duplique pas les objets imbriqués.
  • Utilisez une copie superficielle pour créer un instantané de l'état d'un objet tout en partageant certaines données sous-jacentes entre les objets d'origine et copiés.
  • Utilisez une copie complète si vous souhaitez modifier une réplique d'un objet sans affecter l'original. Cela génère des copies indépendantes des objets imbriqués, garantissant que toute modification apportée à la copie ne s'applique pas à l'original.
  • La copie approfondie est essentielle lorsque vous avez besoin de copies indépendantes de structures de données imbriquées, principalement lorsqu'il s'agit de hiérarchies d'objets récursives ou complexes.

Performances et considérations

Étant donné que la copie superficielle ne génère pas de nouvelles instances d'objets imbriqués, elle s'exécute généralement plus rapidement et utilise moins de mémoire que la copie approfondie. Cependant, l'original et la copie superficielle peuvent avoir des effets secondaires indésirables liés à la modification des éléments internes partagés.

En particulier pour les structures de données volumineuses et profondément imbriquées, la copie profonde, une procédure récursive, peut être plus lent et utiliser plus de mémoire. Cependant, il garantit une indépendance totale entre l’original et la copie complète, ce qui rend la manipulation complexe des données plus sécurisée.

La meilleure option de copie pour vos données

De nombreux langages de programmation utilisent le concept de copie superficielle et profonde. Le comprendre vous permet de manipuler les données sans conséquences imprévues.

En utilisant des techniques de copie superficielle et profonde, vous pouvez sélectionner la meilleure approche pour dupliquer vos structures de données en toute sécurité. En comprenant les effets sur vos données, vous obtiendrez des résultats plus fiables et prévisibles de votre code.