Problème d'affectation à propos de la liste liste en Python

Problème d'affectation à propos de la liste liste en Python

    Cet article enregistre principalement les problèmes rencontrés dans le processus d'attribution de la liste de liste, et résume les connaissances liées à la copie de la liste.

0. Origine du problème

    La raison de cet article est que lors de l'utilisation de l'affectation directe de la liste b=a, les résultats obtenus sont différents de ceux attendus. Plus tard, il a été découvert que l'utilisation directe du signe égal = pour affecter des valeurs à la liste provoquerait une série de problèmes, de sorte que les différences entre , , et les trois 赋值sont 浅拷贝décrites 深拷贝.

1. Méthode d'affectation des listes de listes

    En python, l'affectation d'objet est une simple référence d'objet, différente de C++, comme illustré dans l'exemple suivant :

a = ['a', 'b', 'c']
b = a   # 采用简单的=赋值
print(a==b)

# 下面是输出结果:
True

    Dans le cas ci-dessus, b et a sont identiques, ils pointent vers le même morceau de mémoire, et b est juste un alias de a, qui est une référence. Nous pouvons utiliser si a et b sont identiques pour juger, retourner True, indiquant qu'ils ont la même adresse et le même contenu.
    Les opérations d'affectation (y compris les objets en tant que paramètres et valeurs de retour) n'ouvrent pas de nouvel espace mémoire, elles copient simplement la référence du nouvel objet. En d'autres termes, il n'y a pas de surcharge de mémoire autre que le nom b.
    Modifier a affecte b ; de même, modifier b affecte a. L'exemple suivant tente de modifier b et d'ajouter un nouvel élément 'd' à la fin. En observant les résultats de sortie, on constate qu'en modifiant la liste b, la liste a sera également modifiée, car les deux utilisent le même espace mémoire.

a = ['a', 'b', 'c']
b = a
b.append('d')
print('a = {}'.format(a))
print('b = {}'.format(b))

# 下面是输出结果:
a = ['a', 'b', 'c', 'd']
b = ['a', 'b', 'c', 'd']

2. copie superficielle

    Une copie superficielle crée un nouvel objet dont le contenu est une référence à l'objet d'origine.
    La copie superficielle a trois formes : 切片操作, 工厂函数, copy模块la fonction de copie dans. Par exemple, pour ce qui précède a :
    1. Opération de découpage : b = a[:]ou b = [each for each in a]
    2. Fonction d'usine : b = list(a)
    3. Fonction de copie : b = copy.copy(a)#Lorsque vous utilisez , le b généré par la copie superficielle import copydu module
    n'est plus a. L'utilisation consiste à trouver qu'ils sont pas le même objet, et utilisez id pour afficher , a constaté qu'ils ne pointent pas vers le même morceau de mémoire. Mais lorsque nous utilisons id(x) pour x dans a et id(x) pour x dans b, nous pouvons voir que les adresses des éléments qu'ils contiennent sont les mêmes.
    Dans ce cas, a et b sont des objets différents, et la modification de b ne devrait théoriquement pas affecter a. Par exemple b.append([4,5]). L'effet de code est le suivant :

a = ['a', 'b', 'c', ['yellow', 'red']]
b = a[:]  # 采用了切片操作对列表b进行赋值
b.append('green') # 对列表b执行添加元素操作
print('a = {}'.format(a))
print('b = {}'.format(b))

# 下面是输出结果:
a = ['a', 'b', 'c', ['yellow', 'red']]  # a中的元素不发生变化
b = ['a', 'b', 'c', ['yellow', 'red'], 'green']  # b中增加了一个元素'green'

    Mais il convient de noter que la raison pour laquelle la copie superficielle est appelée copie superficielle est qu'elle ne copie qu'un seul calque et qu'il existe une liste imbriquée dans A. Si nous la modifions, la situation sera différente.
    a[3].append("bleu"). En regardant b, vous constaterez que b a également changé. C'est parce que vous avez modifié la liste imbriquée. La modification de l'élément externe modifiera ses références, les faisant pointer vers d'autres emplacements, modifiant les éléments de la liste imbriquée, et l'adresse de la liste ne changera pas, pointant vers le même emplacement. code afficher comme ci-dessous:

a = ['a', 'b', 'c', ['yellow', 'red']]
b = a[:]  # 采用了切片操作对列表b进行赋值
a[3].append('blue')  # 在a列表中的第3个元素中增加元素'blue',由于a[3]本身也是一个列表,从而是在列表后增加了元素'blue',从输出结果中可以看出来。
print('a = {}'.format(a))
print('b = {}'.format(b))

# 下面是输出结果:
a = ['a', 'b', 'c', ['yellow', 'red', 'blue']]
b = ['a', 'b', 'c', ['yellow', 'red', 'blue']]

3. Copie profonde

    La copie en profondeur n'a qu'une seule forme, la fonction copy模块dans deepcopy.
    Correspondant à la copie superficielle, la copie profonde copie tous les éléments de l'objet, y compris les éléments imbriqués à plusieurs niveaux. Par conséquent, son surcoût de temps et d'espace est élevé.
    Aussi pour la, si vous utilisez b = copy.deepcopy(a), la modification de b n'affectera pas a. Même si la liste imbriquée a un niveau plus profond, cela n'aura aucun effet, car l'objet copié en profondeur est simplement un tout nouvel objet, qui n'est plus lié à l'objet d'origine. L'exemple de code est le suivant :

import copy
a = ['a', 'b', 'c', ['yellow', 'red']]
b = copy.deepcopy(a)   # 采用深拷贝对a进行深拷贝操作
b.append('xyz')
print('a = {}'.format(a))
print('b = {}'.format(b))

# 下面是输出结果:
a = ['a', 'b', 'c', ['yellow', 'red']]   # 使用深拷贝,对b的修改不会影响到a
b = ['a', 'b', 'c', ['yellow', 'red'], 'xyz']

    Ou utilisez le code suivant :

import copy
a = ['a', 'b', 'c', ['yellow', 'red']]
b = copy.deepcopy(a)   # 采用深拷贝对a进行深拷贝操作
a[3].append('crazy')
print('a = {}'.format(a))
print('b = {}'.format(b))

# 下面是输出结果:
a = ['a', 'b', 'c', ['yellow', 'red', 'crazy']]  
b = ['a', 'b', 'c', ['yellow', 'red']]   # 对a的修改不会影响到b

    Ou utilisez le code suivant :

import copy
a = ['a', 'b', 'c', ['yellow', 'red']]
b = copy.deepcopy(a)   # 采用深拷贝对a进行深拷贝操作
a[3].append('crazy')
b.append('dddd')
print('a = {}'.format(a))
print('b = {}'.format(b))

# 下面是输出结果:
a = ['a', 'b', 'c', ['yellow', 'red', 'crazy']]
b = ['a', 'b', 'c', ['yellow', 'red'], 'dddd']

4. Rappel sur l'opération de copie

    1. Pour les types non-conteneurs, tels que les nombres, les caractères et les autres types "atomiques", la copie n'existe pas. Tous générés sont des références à l'objet d'origine.

    2. Si la valeur de la variable tuple contient un objet de type atomique, même si une copie complète est utilisée, seule une copie superficielle peut être obtenue.

5. Références

    (1) Expliquer en détail la copie superficielle et la copie profonde
    (2) Affectation de liste à une autre liste_Python petite connaissance : la méthode d'affectation de List ne peut pas être directement égale à

おすすめ

転載: blog.csdn.net/weixin_43981621/article/details/123247342