TransWikia.com

Why do my numpy constructs ignore tuple deconstruction?

Stack Overflow Asked by trisimix on February 16, 2021

edit: Let me clarify the mystery variables from original post

Assign some variables

WHITE = 0 #UP
BLUE = 1 #DOWN
ORANGE = 2 #LEFT
GREEN = 3 #FRONT
RED = 4 #RIGHT
YELLOW = 5 #BACK

First, I create a janky matrix:

cube = np.array([
        np.array([
          np.array([WHITE, WHITE, WHITE]),np.array([WHITE, WHITE, WHITE]), np.array([WHITE, WHITE, WHITE])
        ]),
        np.array([
         np.array([BLUE, BLUE, BLUE]), np.array([BLUE, BLUE, BLUE]), np.array([BLUE, BLUE, BLUE])
        ]),
        np.array([
         np.array([ORANGE, ORANGE, ORANGE]), np.array([ORANGE, ORANGE, ORANGE]), np.array([ORANGE, ORANGE, ORANGE])
        ]),
        np.array([
         np.array([GREEN, GREEN, GREEN]), np.array([GREEN, GREEN, GREEN]), np.array([GREEN, GREEN, GREEN])
        ]),
        np.array([
         np.array([RED, RED, RED]), np.array([RED, RED, RED]), np.array([RED, RED, RED])
        ]),
        np.array([
         np.array([YELLOW, YELLOW, YELLOW]), np.array([YELLOW, YELLOW, YELLOW]), np.array([YELLOW, YELLOW, YELLOW])
        ])
      ])

The np.arrays are one of my attempts at debugging.

Next, I attempt to swap columns, rows, etc. with tuple deconstruction:

rubiks[LEFT][:,2], rubiks[DOWN][0] = rubiks[DOWN][0], rubiks[LEFT][:,2]

The result is as if it were applied iteratively:

[[1 1 1]
  [1 1 1]
  [1 1 1]]

 [[2 2 1]
  [2 2 1]
  [2 2 1]]

It should be:

[[2 2 2]
  [1 1 1]
  [1 1 1]]

 [[2 2 1]
  [2 2 1]
  [2 2 1]]

I assume I am misunderstanding something, but shouldn’t this swap the values like intended?

One Answer

The slicing on the right side generates references (or 'view' in numpy's terminology). If you force a copy, you can get the expected behavior.

import numpy as np
a = np.array([1, 2])
a[:1], a[1:] = a[1:], a[:1]
print(a) # [2 2]

import numpy as np
a = np.array([1, 2])
a[:1], a[1:] = a[1:].copy(), a[:1].copy()
print(a) # [2 1]

Multi-variable assignment is essentially a tuple packing & unpacking. Numpy slice at the right side of an assignment expression will only provide a reference instead of a copy at the time when the right-side tuple is made. When the second assignment take effect, the underlying storage of a has already been modified.

https://numpy.org/doc/stable/reference/arrays.indexing.html#basic-slicing-and-indexing

In general, avoid figuring out if a numpy slice would automatically be a copy. Take a copy when it is logically necessary.

Correct answer by Blownhither Ma on February 16, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP