2
votes

Résultat inattendu lors de l'utilisation de l'affectation de tranche sur une dimension externe dans des listes python imbriquées

Lors de l'utilisation du code suivant en python 3.7.2, l'affectation est ignorée en silence. Est-ce un résultat attendu?

>>> x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> x
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> x[:][1]=17
>>> x
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Existe-t-il un meilleur moyen d'utiliser des tranches pour obtenir le résultat escompté en remplaçant la 2e colonne par 17? Btw., J'obtiens le même résultat en utilisant [17, 17, 17] pour correspondre à la dimension.

Edit: Juste pour éviter une certaine confusion. Le résultat attendu était [[1, 17, 3], [4, 17, 6], [7, 17, 9]].


4 commentaires

Pour clarifier, votre résultat attendu est-il [[1, 2, 3], 17, [7, 8, 9]] ? Si tel est le cas, utilisez x [1] = 17 .


x [:] crée une copie superficielle de la liste, puis vous remplacez le deuxième élément de la copie .


Le tableau Numpy serait une autre option que vous pouvez envisager


La clé ici est de comprendre que les objets list n'ont pas de lignes et de colonnes . Les objets list sont des listes hétérogènes d'objets Python. Ils n'ont aucune notion de dimensionnalité, mais plutôt, ils ont tous une seule dimension et l'ordinalité de cette dimension est la longueur de la liste.


5 Réponses :


1
votes

cherchez-vous ceci?:

[[1, 17, 3], [4, 17, 6], [7, 17, 9]]

Le résultat est:

x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
y=[[l[0],17,l[2]] for l in x]
print(y)


0 commentaires

4
votes

x [:] crée une copie de la liste d'origine et de cette nouvelle liste modifiée sur place.
Cependant, cette liste créée est inaccessible (car il n'y a pas de référence). Si vous souhaitez obtenir la deuxième sous-liste en tant que [17,17,17] c'est-à-dire x [0] = [17 for _ in x [0]]

mais si vous voulez que ce soit simplement [17] , alors x [0] = [17]

Modifier: OK, on ​​dirait que j'ai mal compris la question, on dirait que vous voulez Traitez cela comme une sorte de matrice. Pour les listes python normales et les listes imbriquées, il n'y a pas de tel sucre syntaxique, vous devrez créer une boucle for:

for sublist in x:
    sublist[1] = 17

Avec les comprenhensions de liste, vous auriez besoin de créer une copie, ce qui n'est pas nécessaire en premier lieu IMO. Mais si vous le souhaitez

copied_and_modified_x = [[sublist [0], 17, sublist [2]] for subist in x]


5 commentaires

"et cette nouvelle liste modifiée sur place" et supprimée


il n'est pas supprimé, je pense qu'il est toujours accessible via _ , au moins dans le Python REPL, sinon, oui, il est rejeté


Je ne crois pas que ce soit ce que veut l'OP, c'est mettre la première ligne à 17, l'OP veut la deuxième colonne


Non, non, non. L'instruction d'affectation ne correspond pas à une valeur, elle n'est donc même pas enregistrée dans une session REPL.


Merci, j'ai manqué le point que [:] fait une copie superficielle. Je suppose que je dois parcourir la liste imbriquée.



1
votes

id (x) et id (x [:]) sont différents, car x [:] crée une copie superficielle de x . Ainsi, lorsque vous écrivez

[[1, 17, 3], [4, 5, 6], [7, 8, 9]] 139933444652552
[[1, 17, 3], [4, 5, 6], [7, 8, 9]] 139933416357064

Vous créez une nouvelle copie superficielle de x et vous modifiez le premier élément de la première sous-liste par 17. Mais, le nouveau Le résultat du résultat n'a pas de référence, donc je ne peux pas accéder à son contenu.

Vous pouvez faire ceci pour obtenir le résultat souhaité:

a = x[:] # creates a shallow copy of x
a[0][1] = 17
print(x, id(x))
print(a, id(a))

Résultat:

x[:][0][1] = 17


0 commentaires

0
votes

Il n'y a aucune raison d'utiliser des tranches de liste si le résultat souhaité est

x = [[1, 2, 3], [17, 17, 17], [7, 8, 9]]

Vous devriez simplement faire:

x [1] = [17,17,17]

Lorsque vous utilisez une tranche, cela crée un nouvel objet égal à x, donc il ne sauvegarde pas sur la variable x.


0 commentaires

0
votes
2 5 8

0 commentaires