I am in a situation where I need to dynamically slice an array of variable shape/ dimension. So I assemble a string to access it.
This works fine when accessing the data.
some_data = eval("arr[:,[ci]]")
#or
some_data = eval("arr[:,[ci],:]")
#or
some_data = eval("arr[:,:,:,[ci]]")
#etc.
But the limitations of eval()
prevent me from assigning using this approach.
eval("arr[:,[ci]]") = some_data
Is there a way I can slice without eval()
?
CodePudding user response:
In Python, the indexing operation for a type is implemented by the __getitem__
/__setitem__
/__delitem__
magic methods. To understand how indexing syntax is interpreted, and thus how these methods are called, we can simply define our own class:
class test:
def __getitem__(self, idx):
return idx
test()[:, [1,2,3], ...]
# result: (slice(None, None, None), [1, 2, 3], Ellipsis)
This slice
type is a built-in type mentioned earlier in the same documentation, with a link to more specific information.
Ellipsis
is simply the name of the object created by the literal syntax ...
. It's what Numpy uses to represent the complete extent of any number of axes - so this lets us avoid worrying about the dimensionality of the array we're working with.
The important thing to realize is that we can use that same index tuple directly, to get the same result.
Thus, given a dimension along which to slice with [ci]
, we can construct the necessary tuple, and index with it:
all = slice(None)
def make_index(ci, dimension):
return (all,) * dimension ([ci], Ellipsis)
# Now we can do things like:
arr[make_index(ci, dimension)] = some_data