Given an 2-dimensional tensor in numpy (or in pytorch), I can partially slice along all dimensions at once as follows:
>>> import numpy as np
>>> a = np.arange(2*3).reshape(2,3)
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> a[1:,1:]
array([[ 5,  6,  7],
       [ 9, 10, 11]])
How can I achieve the same slicing pattern regardless of the number of dimensions in the tensor if I do not know the number of dimensions at implementation time? (i.e. I want a[1:] if a has only one dimension, a[1:,1:] for two dimensions, a[1:,1:,1:] for three dimensions, and so on) 
It would be nice if I could do it in a single line of code like the following, but this is invalid:
a[(1:,) * len(a.shape)]  # SyntaxError: invalid syntax
I am specifically interested in a solution that works for pytorch tensors (just substitute torch for numpy above and the example is the same), but I figure it is likely and best if the solution works for both numpy and pytorch.
Answer: Making a tuple of slice objects does the trick:
a[(slice(1,None),) * len(a.shape)]
Explanation:
slice is a builtin python class (not tied to numpy or pytorch) which provides an alternative to the subscript notation for describing slices.  The answer to a different question suggests using this as a way to store slice information in python variables. The python glossary points out that 
The bracket (subscript) notation uses slice objects internally.
Since the __getitem__ methods for numpy ndarrays and pytorch tensors support multi-dimensional indexing with slices, they must also support multidimensional indexing with slice objects, and so we can make a tuple of those slices that of the right length.
Btw, you can see how python uses the slice objects by creating a dummy class as follows and then do slicing on it:
class A(object):
    def __getitem__(self, ix):
        return ix
print(A()[5])  # 5
print(A()[1:])  # slice(1, None, None)
print(A()[1:,1:])  # (slice(1, None, None), slice(1, None, None))
print(A()[1:,slice(1,None)])  #  (slice(1, None, None), slice(1, None, None))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With