You can easily achieve that by using np.ix_ and range():
import numpy as np
A =np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
A[np.ix_(range(-1,1),range(-1,2))]
Output:
array([[15, 12, 13],
[ 3, 0, 1]])
To avoid the possible error in a scenario like when for example the range of the sliced is (5,5) in a 4x4 matrix, you could try this:
import numpy as np
A =np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
s1=[5,5]
s1=list(map(lambda x:(x+A.shape[0])%A.shape[0],s1)) if s1[0]>s1[1] else s1
s1=list(map(lambda x:(x+A.shape[0])%A.shape[0],range(min(s1),max(s1)))) if s1[0]%A.shape[0]!=s1[1]%A.shape[0] else [(s1[0]+A.shape[0])%A.shape[0]]
s2=[-1,2]
s2=list(map(lambda x:(x+A.shape[0])%A.shape[0],s2)) if s2[0]>s2[1] else s2
s2=list(map(lambda x:(x+A.shape[0])%A.shape[0],range(min(s2),max(s2)))) if s2[0]%A.shape[0]!=s2[1]%A.shape[0] else [(s2[0]+A.shape[0])%A.shape[0]]
A[np.ix_(s1,s2)]