如何获取numpy ndarray的非平凡(非连续)视图?
Great question! Let's break this down clearly—first, the key point: you can create non-trivial views of an ndarray only if the new element ordering can be represented by adjusting the array's strides (the byte offsets between elements along each axis) without rearranging the underlying data in memory. For your specific 4D-to-2D reshaping need, this is absolutely feasible, and we can do it safely without copying data.
Solution for Your 4D-to-2D Use Case
Let's start with your sample 4D array:
import numpy as np x = np.array([[[[1, 1], [1, 1]],[[2, 2], [2, 2]]], [[[3, 3], [3, 3]], [[4, 4], [4, 4]]]])
Your desired view z follows the indexing rule a = u*S + s and b = v*T + t. To get this as a view, we just need to adjust the axis order first, then reshape:
# Rearrange axes to (u, s, v, t) to align with your a/b indexing logic x_transposed = x.transpose(0, 2, 1, 3) # Reshape to (U*S, V*T) z = x_transposed.reshape(4, 4)
Verify this is a view (not a copy):
print(z.flags.owndata) # Output: False (z doesn't own its data) print(z.base is x) # Output: True (z's base is the original array)
And z exactly matches your desired output:
print(z) # [[1 1 2 2] # [1 1 2 2] # [3 3 4 4] # [3 3 4 4]]
Why This Works
- Transpose returns a view: When you use
transpose, NumPy doesn't copy any data—it just modifies the array's metadata (axis order and strides). For your original array with shape(U, V, S, T), transposing to(U, S, V, T)swaps the positions of theVandSaxes, which aligns elements with youraindex (u*S + s). - Reshape preserves the view: After transposing, reshaping to
(U*S, V*T)works as a view because the total number of elements is the same, and NumPy can compute new strides directly from the transposed array's strides. Even though the transposed array is non-contiguous in memory, reshape doesn't require contiguity to return a view.
Answers to Your Other Questions
- Can you get a view like
[2,4,3,1]from[1,2,3,4]? No, you can't. This arbitrary permutation can't be represented with simple stride adjustments—each element's memory address isn't spaced by a consistent offset relative to the previous one. Fancy indexing will always return a copy here, since it has to rearrange data in memory. - Why didn't your initial reshape/transpose attempts work? Standard
reshapeuses C-order (row-major) by default, which flattens your original array asu → v → s → t—this doesn't match your desireda = u*S + slogic. Transposing to(U, S, V, T)first fixes this axis order before reshaping. - Is this possible in pure Python? Yes! You don't need C/C++ code—NumPy's built-in
transposeandreshape(when used correctly) handle this in pure Python by manipulating the array's metadata (strides and axis order) without touching the underlying data. Thendarray.sortmethod is in-place because it modifies the original data, not because it's using low-level code—view creation is a separate operation that works by reinterpreting existing data.
A Note on np.as_strided
You mentioned trying as_strided—while it can create custom views, it's risky because it can easily lead to out-of-bounds memory access. For your use case, transpose + reshape is safer and more readable, and it achieves exactly what you need without any risk.
内容的提问来源于stack exchange,提问作者MaxSchambach

