commen=E7ant de bidouiller depuis quelques semaines avec Python 2.5, je
suis tomb=E9 sur la surprise suivante.
>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D RESTART =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>>> old =3D ['abcdef\n','ghijkl\n']
>>> new =3D old
>>> old
['abcdef\n', 'ghijkl\n']
>>> new
['abcdef\n', 'ghijkl\n']
>>> new[1]=3D new[1][0:2] +'zz'+new[1][4:]
>>> new
['abcdef\n', 'ghzzkl\n']
>>> old
['abcdef\n', 'ghzzkl\n']
>>>
Autrement dit la modification d'un =E9l=E9ment de la liste new entraine la
modification =E0 l'identique de la liste old
bien que old n'apparaisse jamais =E0 gauche d'une =E9galit=E9 apr=E8s sa
cr=E9ation.
Cette surprenante propri=E9t=E9 ne me semble pas clairement document=E9e
dans le tutoriel que j'utilise.
Elle concerne les listes, mais pas les objets plus simples : si old
est une simple chaine, on la retrouve inchang=E9e =E0 la fin des
op=E9rations :
>>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D RESTART =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>>> old =3D 'abcdef\n'
>>> new =3D old
>>> old
'abcdef\n'
>>> new
'abcdef\n'
>>> new=3D new[0:2] +'zz'+new[4:]
>>> new
'abzzef\n'
>>> old
'abcdef\n'
>>>
Si, comme je le suppose, il s'agit l=E0 d'une propri=E9t=E9 naturelle connue=
des listes, quelqu'un peut -il me dire comment faire pour conserver la
liste old sans modification pour pouvoir cr=E9er plusieurs listes
new1,new2,new3... en applicant des alt=E9rations diff=E9rentes =E0 la m=EAme=
base old
Merci d'avance =E0 qui pourra m'=E9clairer
Cordialement
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Bruno Desthuilliers
Bonjour,
commençant de bidouiller depuis quelques semaines avec Python 2.5, je suis tombé sur la surprise suivante.
old = ['abcdefn','ghijkln'] new = old old ['abcdefn', 'ghijkln']
new ['abcdefn', 'ghijkln']
new[1]= new[1][0:2] +'zz'+new[1][4:] new ['abcdefn', 'ghzzkln']
old ['abcdefn', 'ghzzkln']
Autrement dit la modification d'un élément de la liste new entraine la modification à l'identique de la liste old bien que old n'apparaisse jamais à gauche d'une égalité après sa création. Cette surprenante propriété ne me semble pas clairement documentée dans le tutoriel que j'utilise.
Cette "surprenante propriété" concerne *tous* les objets *sans exception* (si si). Elle s'explique par le fait qu'en Python, une "variable" est en fait une paire nom=>référence objet dans un espace de nommage (généralement une table de hachage). L'assignation consiste donc en fait a associer un nom à une référence sur un objet. Un même objet peut bien sûr être associé à plusieurs noms simultanément (dans un même espace de nommage ou dans des espaces de nommage différents), ce qui est le cas ci-dessus : 'old' et 'new' pointent tous les deux sur le même objet. Tu peux le vérifier avec le test d'identité: print new is old => True
Par ailleurs, les accès indexés (listes, dicts etc) sont traduits en appels aux méthodes __getitem__ et __setitem__, la seconde modifiant l'état de l'objet.
Bref, ce que tu observes est parfaitement normal : que tu y accèdes par le nom 'new' ou par le nom 'old', tu travailles sur un seul et même objet.
En bref : Python ne copie jamais rien si tu ne le demandes pas explicitement (cf plus bas).
Elle concerne les listes, mais pas les objets plus simples : si old est une simple chaine, on la retrouve inchangée à la fin des opérations :
Attention, tes deux snippets sont très différents : dans le premier cas, tu *modifies* un objet existant, dans le second tu *réaffectes* un nouvel objet à un nom existant.
Accessoirement, les chaines sont immutables (comme les nombres et les tuples), tu ne peux donc pas faire un test équivalent au premier !-)
old = 'abcdefn' new = old old 'abcdefn'
new 'abcdefn'
new= new[0:2] +'zz'+new[4:] new 'abzzefn'
old 'abcdefn'
Si, comme je le suppose, il s'agit là d'une propriété naturelle connue des listes, quelqu'un peut -il me dire comment faire pour conserver la liste old sans modification pour pouvoir créer plusieurs listes new1,new2,new3... en applicant des altérations différentes à la même base old
En faisant une copie de la liste. La solution la plus simple:
old = [range(3), range(3,6)] old [[0, 1, 2], [3, 4, 5]]
new = old[:] new[0] = "allo" new ['allo', [3, 4, 5]]
old [[0, 1, 2], [3, 4, 5]]
Attention toutefois, c'est une copie "superficielle" - new[1] et old[1] référencent le même objet :
new[1][0] = 42 new ['allo', [42, 4, 5]]
old [[0, 1, 2], [42, 4, 5]]
Si tu veux une copie "profonde" (c'est à dire une copie non seulement de la liste mais aussi de tous les objets qu'elle contient), regarde du côté de copy.deepcopy()
HTH
Bonjour,
commençant de bidouiller depuis quelques semaines avec Python 2.5, je
suis tombé sur la surprise suivante.
old = ['abcdefn','ghijkln']
new = old
old
['abcdefn', 'ghijkln']
new
['abcdefn', 'ghijkln']
new[1]= new[1][0:2] +'zz'+new[1][4:]
new
['abcdefn', 'ghzzkln']
old
['abcdefn', 'ghzzkln']
Autrement dit la modification d'un élément de la liste new entraine la
modification à l'identique de la liste old
bien que old n'apparaisse jamais à gauche d'une égalité après sa
création.
Cette surprenante propriété ne me semble pas clairement documentée
dans le tutoriel que j'utilise.
Cette "surprenante propriété" concerne *tous* les objets *sans
exception* (si si). Elle s'explique par le fait qu'en Python, une
"variable" est en fait une paire nom=>référence objet dans un espace de
nommage (généralement une table de hachage). L'assignation consiste donc
en fait a associer un nom à une référence sur un objet. Un même objet
peut bien sûr être associé à plusieurs noms simultanément (dans un même
espace de nommage ou dans des espaces de nommage différents), ce qui est
le cas ci-dessus : 'old' et 'new' pointent tous les deux sur le même
objet. Tu peux le vérifier avec le test d'identité:
print new is old
=> True
Par ailleurs, les accès indexés (listes, dicts etc) sont traduits en
appels aux méthodes __getitem__ et __setitem__, la seconde modifiant
l'état de l'objet.
Bref, ce que tu observes est parfaitement normal : que tu y accèdes par
le nom 'new' ou par le nom 'old', tu travailles sur un seul et même objet.
En bref : Python ne copie jamais rien si tu ne le demandes pas
explicitement (cf plus bas).
Elle concerne les listes, mais pas les objets plus simples : si old
est une simple chaine, on la retrouve inchangée à la fin des
opérations :
Attention, tes deux snippets sont très différents : dans le premier cas,
tu *modifies* un objet existant, dans le second tu *réaffectes* un
nouvel objet à un nom existant.
Accessoirement, les chaines sont immutables (comme les nombres et les
tuples), tu ne peux donc pas faire un test équivalent au premier !-)
old = 'abcdefn'
new = old
old
'abcdefn'
new
'abcdefn'
new= new[0:2] +'zz'+new[4:]
new
'abzzefn'
old
'abcdefn'
Si, comme je le suppose, il s'agit là d'une propriété naturelle connue
des listes, quelqu'un peut -il me dire comment faire pour conserver la
liste old sans modification pour pouvoir créer plusieurs listes
new1,new2,new3... en applicant des altérations différentes à la même
base old
En faisant une copie de la liste. La solution la plus simple:
old = [range(3), range(3,6)]
old
[[0, 1, 2], [3, 4, 5]]
new = old[:]
new[0] = "allo"
new
['allo', [3, 4, 5]]
old
[[0, 1, 2], [3, 4, 5]]
Attention toutefois, c'est une copie "superficielle" - new[1] et old[1]
référencent le même objet :
new[1][0] = 42
new
['allo', [42, 4, 5]]
old
[[0, 1, 2], [42, 4, 5]]
Si tu veux une copie "profonde" (c'est à dire une copie non seulement de
la liste mais aussi de tous les objets qu'elle contient), regarde du
côté de copy.deepcopy()
commençant de bidouiller depuis quelques semaines avec Python 2.5, je suis tombé sur la surprise suivante.
old = ['abcdefn','ghijkln'] new = old old ['abcdefn', 'ghijkln']
new ['abcdefn', 'ghijkln']
new[1]= new[1][0:2] +'zz'+new[1][4:] new ['abcdefn', 'ghzzkln']
old ['abcdefn', 'ghzzkln']
Autrement dit la modification d'un élément de la liste new entraine la modification à l'identique de la liste old bien que old n'apparaisse jamais à gauche d'une égalité après sa création. Cette surprenante propriété ne me semble pas clairement documentée dans le tutoriel que j'utilise.
Cette "surprenante propriété" concerne *tous* les objets *sans exception* (si si). Elle s'explique par le fait qu'en Python, une "variable" est en fait une paire nom=>référence objet dans un espace de nommage (généralement une table de hachage). L'assignation consiste donc en fait a associer un nom à une référence sur un objet. Un même objet peut bien sûr être associé à plusieurs noms simultanément (dans un même espace de nommage ou dans des espaces de nommage différents), ce qui est le cas ci-dessus : 'old' et 'new' pointent tous les deux sur le même objet. Tu peux le vérifier avec le test d'identité: print new is old => True
Par ailleurs, les accès indexés (listes, dicts etc) sont traduits en appels aux méthodes __getitem__ et __setitem__, la seconde modifiant l'état de l'objet.
Bref, ce que tu observes est parfaitement normal : que tu y accèdes par le nom 'new' ou par le nom 'old', tu travailles sur un seul et même objet.
En bref : Python ne copie jamais rien si tu ne le demandes pas explicitement (cf plus bas).
Elle concerne les listes, mais pas les objets plus simples : si old est une simple chaine, on la retrouve inchangée à la fin des opérations :
Attention, tes deux snippets sont très différents : dans le premier cas, tu *modifies* un objet existant, dans le second tu *réaffectes* un nouvel objet à un nom existant.
Accessoirement, les chaines sont immutables (comme les nombres et les tuples), tu ne peux donc pas faire un test équivalent au premier !-)
old = 'abcdefn' new = old old 'abcdefn'
new 'abcdefn'
new= new[0:2] +'zz'+new[4:] new 'abzzefn'
old 'abcdefn'
Si, comme je le suppose, il s'agit là d'une propriété naturelle connue des listes, quelqu'un peut -il me dire comment faire pour conserver la liste old sans modification pour pouvoir créer plusieurs listes new1,new2,new3... en applicant des altérations différentes à la même base old
En faisant une copie de la liste. La solution la plus simple:
old = [range(3), range(3,6)] old [[0, 1, 2], [3, 4, 5]]
new = old[:] new[0] = "allo" new ['allo', [3, 4, 5]]
old [[0, 1, 2], [3, 4, 5]]
Attention toutefois, c'est une copie "superficielle" - new[1] et old[1] référencent le même objet :
new[1][0] = 42 new ['allo', [42, 4, 5]]
old [[0, 1, 2], [42, 4, 5]]
Si tu veux une copie "profonde" (c'est à dire une copie non seulement de la liste mais aussi de tous les objets qu'elle contient), regarde du côté de copy.deepcopy()