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 overwriting using this approach.
eval("arr[:,[ci]]") = some_data
Is there a way I can slice without eval()?
>Solution :
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