reshape() returns a view when data is contiguous in memory; else a copy.
flatten() always returns a copy, safe for independent modifications.
ravel() returns a view when possible; faster but can mutate original.
transpose() returns a view with reordered axes, never copies data.
squeeze() and expand_dims() adjust dims of size 1 and 0, zero memory overhead.
✦ Definition~90s read
What is NumPy Shape Manipulation?
NumPy shape manipulation functions let you restructure array dimensions without copying data—most of the time. The core idea is that a NumPy array is a block of memory with metadata (shape, strides, dtype). Changing shape just reinterprets that metadata, not the underlying bytes.
★
Think of a NumPy array like a row of lockers.
This is why reshape() is O(1) and why ravel() can return a view or a copy depending on memory layout. The gotcha: ravel() returns a view when possible (contiguous arrays), but a copy when the array is non-contiguous (e.g., after a transpose or slice).
That view shares memory with the original—mutate it, and you silently corrupt your source data. This is a common trap in ML pipelines where you flatten a transposed feature matrix, modify it for normalization, and wonder why your original samples changed.
Alternatives: flatten() always returns a copy (safe but allocates memory), while reshape(-1) gives you explicit control. Use ravel() only when you know the array is C-contiguous and you want zero-copy performance. For production ML data pipelines, prefer flatten() or explicit copies unless you've profiled and proven the memory overhead matters.
Plain-English First
Think of a NumPy array like a row of lockers. ravel() is like looking at the lockers in a straight line — if the lockers are already in a neat row, you just point to them (a view), but if they're scattered after a transpose, you have to copy the items into a new row (a copy). If you change something in the copied row, the original lockers stay the same, but if you change the view, you mess up the original lockers too.
Reshaping arrays is one of the most frequent NumPy operations, especially when preparing data for machine learning models. A linear layer expects (batch, features). A convolution expects (batch, channels, height, width). Getting the shape right without introducing bugs requires understanding which operations copy data and which do not.
This guide covers the core shape manipulation functions, the view/copy rules for each, and the practical patterns that come up in real code.
What NumPy Shape Manipulation Actually Does
NumPy shape manipulation is the set of operations that change the dimensions and layout of an array without necessarily altering its underlying data buffer. The core mechanic is that arrays are stored as contiguous blocks of memory, and reshaping operations reinterpret the strides and shape metadata to present a new view of the same data. This is fundamentally different from copying data — a reshape is O(1) in memory and time, while a copy is O(n).
In practice, shape manipulation works by adjusting the array's shape tuple and stride tuple. For example, reshaping a (4, 4) array to (16,) keeps the same 64-byte block of floats but changes how NumPy indexes into it. The critical property is contiguity: operations like ravel() return a contiguous 1D view only if the array is already C-contiguous; otherwise, it returns a copy. This distinction is invisible until you modify the view and see the original array change — or fail to change.
Use shape manipulation when you need to feed data into APIs that expect a specific dimensionality, such as machine learning models expecting a flat feature vector, or when broadcasting requires aligned shapes. It matters in real systems because an accidental copy from a non-contiguous array can silently double memory usage and crash a pipeline processing 10 GB of data. Always check .flags.c_contiguous before assuming a view is free.
⚠ View vs. Copy Ambiguity
ravel() returns a view only if the array is C-contiguous; otherwise it returns a copy. Never assume O(1) — verify with .flags.c_contiguous.
📊 Production Insight
A team flattened a (10000, 10000) float32 array that was a transpose view, causing ravel() to copy 400 MB silently, doubling memory and triggering OOM in a Kubernetes pod.
The symptom was a sudden memory spike during a seemingly cheap reshape, with no error until the pod was killed.
Rule: always call np.ascontiguousarray() before ravel() if you need a guaranteed view and are unsure of contiguity.
🎯 Key Takeaway
Shape manipulation is metadata reinterpretation, not data movement — but only when the array is contiguous.
ravel() and reshape can return copies; check contiguity before assuming O(1) behavior.
Always profile memory when flattening large arrays from unknown sources — a hidden copy can crash production pipelines.
thecodeforge.io
Numpy Shape Manipulation
reshape — Changing Shape Without Changing Data
reshape() returns a view when the data is contiguous in memory (which it usually is for freshly created arrays). Use -1 as a wildcard dimension and NumPy computes it from the total element count. This is the most common way to restructure data for ML model inputs.
reshape_demo.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np
a = np.arange(12) # shape (12,)print(a.reshape(3, 4)) # (3, 4)print(a.reshape(2, 6)) # (2, 6)print(a.reshape(2, -1)) # (2, 6) — -1 inferredprint(a.reshape(3, 2, 2)) # (3, 2, 2)# Common ML pattern: add batch dimension
single = np.random.randn(28, 28) # one image
batch = single.reshape(1, 28, 28) # one image in a batchprint(batch.shape) # (1, 28, 28)
Output
(3, 4) view of original data
(1, 28, 28)
Mental Model
The Rubber Band Analogy
Think of reshape as stretching a rubber band – same material, different shape – but only if the band is in one contiguous piece.
If array is contiguous in memory, reshape just changes the stride/offset metadata — no data movement.
If non-contiguous, NumPy silently creates a copy – now you have two rubber bands.
Use -1 dimension to let NumPy calculate the remaining size automatically.
📊 Production Insight
After transpose or fancy indexing, arrays often become non-contiguous.
Calling reshape on a non-contiguous array forces a copy — performance hit, but also breaks the view contract.
Rule: check arr.flags['C_CONTIGUOUS'] before relying on view behavior.
🎯 Key Takeaway
reshape() is a metadata change when possible.
Always verify contiguity before assuming view.
Use -1 for automatic dimension calculation.
Choosing reshape strategy
IfNeed to change shape and fine with potential copy
→
UseUse reshape() directly — fastest.
IfMust guarantee no copy
→
UseCall ascontiguousarray() first, then reshape().
IfNeed to enforce copy
→
UseUse arr.reshape(shape).copy() explicitly.
IfOnly one dimension unknown
→
UseUse -1 as wildcard.
flatten vs ravel — Both Give 1D, Different Memory
flatten() always returns a new array with its own memory. ravel() returns a view when the array is contiguous, else it returns a flattened copy. For most use cases ravel() is faster and memory-efficient, but if you need a guaranteed independent copy that won't mutate the original, use flatten().
flatten_vs_ravel.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np
m = np.array([[1, 2], [3, 4]])
f = m.flatten() # copy — always
r = m.ravel() # view when possible
f[0] = 99print(m[0, 0]) # 1 — flatten copy not linked
r[0] = 99print(m[0, 0]) # 99 — ravel view is linked
Output
1
99
⚠ Hidden dependencies with ravel()
In a data pipeline, if you mutate the result of ravel() you're mutating the original array. This can cause subtle bugs where a seemingly isolated transformation corrupts upstream data. Always use flatten() when you need independence.
📊 Production Insight
flatten() always doubles memory — problematic for arrays > 1GB.
ravel() is zero-copy when contiguous, but introduces aliasing.
Rule: Use ravel() in read-only contexts; use flatten().copy() in read-write pipelines.
🎯 Key Takeaway
flatten() copies every time — safe but costly.
ravel() is fast but can alias.
When in doubt, flatten explicitly.
flatten vs ravel decision
IfData is read-only after flattening
→
UseUse ravel() — faster, less memory.
IfWill modify the result and must not affect original
→
UseUse flatten() — guaranteed copy.
IfUncertain about contiguity and need safety
→
UseUse flatten() or ascontiguousarray + ravel.
thecodeforge.io
Numpy Shape Manipulation
transpose — Reordering Axes
transpose() reverses the order of axes by default (equivalent to .T). You can also pass a tuple to specify the exact axis order. It always returns a view — no data is copied, only the strides and shape metadata are rearranged. This is extremely fast but the result is non-contiguous in memory.
transpose_demo.pyPYTHON
1
2
3
4
5
6
7
8
9
10
import numpy as np
a = np.arange(24).reshape(2, 3, 4)
print(a.shape) # (2, 3, 4)print(a.T.shape) # (4, 3, 2) — reversedprint(a.transpose(0, 2, 1).shape) # (2, 4, 3) — swap last two axes# .T is just shorthand for .transpose()
matrix = np.ones((3, 5))
print(matrix.T.shape) # (5, 3)
Output
(2, 3, 4)
(4, 3, 2)
(2, 4, 3)
(5, 3)
🔥Transpose never copies – but watch the performance
Because transpose returns a view, the data stays in place. However, accessing elements in the transposed order may be slower due to cache misses if the memory layout doesn't match the iteration order. For performance-critical loops, consider converting to contiguous with np.ascontiguousarray().
📊 Production Insight
Transposed arrays break C-contiguity — subsequent ops like .reshape() will trigger copies.
Rule: If you transpose and then need to reshape, combine both operations in one call to avoid an intermediate copy.
🎯 Key Takeaway
transpose() is always a view — no copy.
Result is non-contiguous — subsequent calls may copy.
Explicit axis order avoids surprises.
When to use transpose vs changing stride manually
IfNeed to swap two axes for broadcasting
→
UseUse np.transpose(arr, axes) with explicit order.
IfReverse all axes
→
UseUse arr.T or np.transpose(arr).
IfNeed C-contiguous output for further operations
→
UseTranspose then call np.ascontiguousarray() or use np.moveaxis which may copy.
squeeze and expand_dims — Manage Singleton Dimensions
squeeze() removes dimensions of size 1 from the shape. expand_dims() inserts a new dimension of size 1 at a specified axis. Both return views when possible. They are essential for aligning array shapes before operations like concatenation or broadcasting.
squeeze_expand.pyPYTHON
1
2
3
4
5
6
7
8
9
import numpy as np
a = np.zeros((1, 3, 1, 4)) # shape with two size-1 dimsprint(a.squeeze().shape) # (3, 4)print(a.squeeze(axis=0).shape) # (3, 1, 4) — remove only axis 0
b = np.array([1, 2, 3]) # shape (3,)print(np.expand_dims(b, axis=0).shape) # (1, 3)print(np.expand_dims(b, axis=1).shape) # (3, 1)
Output
(3, 4)
(3, 1, 4)
(1, 3)
(3, 1)
💡Broadcasting helper
Use expand_dims to make arrays broadcastable without manual reshaping. For example, adding a batch dimension: np.expand_dims(single_image, axis=0) gives shape (1, H, W).
📊 Production Insight
squeeze() on selective axes may fail if the axis size is not 1.
expand_dims does not allocate new memory — it's just a view with a new stride.
Rule: Use squeeze(axis=...) when you know the dimension is singleton; use np.squeeze(arr) with no axis to remove all.
🎯 Key Takeaway
squeeze() removes size-1 dims without copying.
expand_dims() adds them without memory overhead.
Both return views — use them freely.
When to squeeze or expand
IfArray has unnecessary singleton dims before ML model
→
UseUse squeeze() to reduce shape.
IfNeed to add dim to make arrays broadcastable
→
UseUse expand_dims or indexing: arr[None, ...].
IfOnly remove specific singleton dims
→
UseUse squeeze(axis=target).
Reshaping in Practice: ML Data Pipeline Patterns
In machine learning, shape manipulation is used constantly to convert between different data layouts. Common patterns: (samples, features) → (batch, channels, height, width) for CNNs; adding batch dimensions; flattening final layers; transposing from (batch, seq, features) to (seq, batch, features) for recurrent networks. Knowing which operations are views vs copies directly impacts memory budgets and training speed.
Every ML layer has an expected shape contract. Reshape is the glue that ensures compatibility without changing the underlying data.
Reshape changes only the metadata — data stays same.
Using -1 lets NumPy auto-calculate one dimension.
Avoid chaining transpose + reshape unless you need the copy.
📊 Production Insight
Large multi-dimensional arrays that are non-contiguous after transpose cause reshape to copy, doubling memory usage.
For a model with activation maps of shape (batch, 1024, 14, 14), a forced copy can add 200MB+ per batch.
Rule: Whenever possible, design the pipeline to produce arrays in the final required memory layout (C-contiguous).
🎯 Key Takeaway
Plan memory layout before building the pipeline.
Views are free; copies cost memory.
Combine operations to avoid intermediate copies.
Reshape strategy for ML pipelines
IfNeed to go from flat to multi-dimensional
→
UseUse reshape(-1, dim1, dim2) — view if contiguous.
IfNeed to add batch dimension
→
UseUse expand_dims(arr, axis=0) — zero copy.
IfNeed to reorder axes for a different model
→
UseUse transpose; then ascontiguousarray if reshaping follows.
The -1 Shortcut: Let NumPy Do the Arithmetic
You don't always know the exact dimensions you need. Or you're reshaping a batch of variable-length sequences and want NumPy to figure out the row count for you. That's where -1 comes in.
Pass -1 for any single dimension and NumPy infers its size from the total number of elements and the other dimensions. If your array has 12 elements and you say reshape(-1, 3), NumPy calculates 4 rows automatically. Mismatch the total? It throws a ValueError fast.
This isn't a party trick. It's essential when you're building ML data pipelines where input shapes change per batch. You know your feature count (columns) but the number of samples is dynamic. reshape(-1, feature_count) keeps your code clean and your pipelines general.
Production Trap:-1 only works for one dimension. Pass it twice and NumPy will tell you exactly where to stick your ambiguity.
BatchReshaper.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// io.thecodeforge — python tutorial
import numpy as np
# Sensors emit 12 readings per sample, variable batch size
batch_samples = np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6,
0.7, 0.8, 0.9, 1.0, 1.1, 1.2])
# Reshape into (samples, 3 features) — rows inferred
feature_matrix = batch_samples.reshape(-1, 3)
print("Feature matrix shape:", feature_matrix.shape)
print(feature_matrix)
# This blows up — two unknowns is not allowedtry:
broken = batch_samples.reshape(-1, -1)
exceptValueErroras e:
print(f"Error: {e}")
Output
Feature matrix shape: (4, 3)
[[0.1 0.2 0.3]
[0.4 0.5 0.6]
[0.7 0.8 0.9]
[1. 1.1 1.2]]
Error: can only specify one unknown dimension
⚠ Production Trap:
Using -1 when the total size doesn't evenly divide the other dimensions triggers a hard crash. Always validate total element count before reshaping real-time streams.
🎯 Key Takeaway
Use -1 for batch dimensions in data pipelines to let NumPy infer row counts automatically.
Order Matters: Row-Major vs Column-Major Reshaping
By default, reshape uses C-style (row-major) ordering. That means it fills the new array by walking through memory row by row. Switch to 'F' for Fortran-style (column-major) ordering, which fills column by column.
Why should you care? Because the same shape and data can produce completely different matrices depending on the order parameter. If you're porting Fortran code, reading binary files from legacy systems, or aligning with column-major frameworks like MATLAB, ignoring order will silently corrupt your results.
The difference: with a 1D array [1,2,3,4,5,6], reshape((2,3), order='C') gives [[1,2,3],[4,5,6]]. Same call with order='F' gives [[1,3,5],[2,4,6]]. Same data, different interpretation. Senior devs check the order parameter before they blame the data.
Senior Shortcut: Use order='A' to preserve the array's existing memory layout. Handy when you're wrapping external libraries that expect specific strides.
When reading binary data from scientific instruments, the memory layout is often column-major. Always verify with np.isfortran(array) before reshaping.
🎯 Key Takeaway
Specify the order parameter explicitly when reshaping — default C-order is safe, but F-order matches legacy systems and external formats.
reshape Returns a View or a Copy — Know Which You're Getting
Most devs assume reshape always returns a view into the original array. That's wrong — and it'll corrupt your data silently in production. When the input is contiguous in memory (C-order), reshape returns a view: zero-copy, instant, shared memory. Modify the view, you modify the original. When the data isn't contiguous — after a transpose, a slice, or any non-trivial indexing — reshape is forced to return a copy. You get a new block of memory, and writes to the result don't touch the original. The kicker: reshape won't warn you which case you're in. You have to check np.shares_memory(a, a.reshape(...)) if correctness depends on it. In ML pipelines where you reshape after slicing validation sets, this is a silent data-leak bug waiting to happen.
check_view_or_copy.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// io.thecodeforge — python tutorial
import numpy as np
# Contiguous array — reshape returns a view
original = np.arange(12).reshape(3, 4)
reshaped = original.reshape(6, 2)
reshaped[0, 0] = 999print(f"Original modified: {original[0, 0]}") # 999 — same memory# Non-contiguous after transpose — reshape returns a copy
transposed = original.T # shape (4,3), not contiguous
reshaped_copy = transposed.reshape(2, 6)
reshaped_copy[0, 0] = 888print(f"Original untouched: {original[0, 0]}") # 999 — different memory# The reliable check:print(f"Shares memory: {np.shares_memory(original, reshaped)}")
Output
Original modified: 999
Original untouched: 999
Shares memory: True
⚠ Production Trap:
After a transpose or fancy indexing, reshape returns a copy. If your training pipeline modifies the reshaped array expecting side effects in the original, you'll introduce a bug that only manifests at scale.
🎯 Key Takeaway
Always verify view-vs-copy with np.shares_memory when reshaping non-contiguous arrays.
Combining reshape with Other Operations Without Intermediate Copies
Chaining reshape after transpose or squeeze creates unnecessary intermediate arrays and wastes memory. The reshape method accepts the final shape directly — combine axis reordering and dimension changes in one call using reshape with order and the target shape. Better yet, use np.moveaxis followed by reshape in a single expression. Real production sin I see daily: someone writes data.transpose(1,0,2).reshape(-1, 64) — that creates a whole new transposed array in memory, then reshapes it. Two allocations for one transformation. Either use np.einsum or just data.reshape(-1, 64).T if you control the layout. The rule: avoid creating temporary arrays you don't need. Downstream in a big-data pipeline, those copies blow up RAM and tank cache performance.
combine_ops_no_copy.pyPYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// io.thecodeforge — python tutorial
import numpy as np
# Three batches, 4x4 images, 3 channels
data = np.random.randn(3, 4, 4, 3)
# BAD — two allocs
bad = data.transpose(0, 3, 1, 2).reshape(-1, 16)
print(f"BAD shape: {bad.shape}, memory: {bad.nbytes} bytes")
# GOOD — single reshape with order='C'# Reorganize memory layout manually, then one reshape
good = np.ascontiguousarray(
np.moveaxis(data, -1, 1)
).reshape(-1, 16)
print(f"GOOD shape: {good.shape}, memory: {good.nbytes} bytes")
# Even cleaner for this pattern: flatten axes directly
efficient = data.reshape(3 * 4 * 4, 3)
print(f"EFFICIENT shape: {efficient.shape}")
Output
BAD shape: (48, 16), memory: 6144 bytes
GOOD shape: (48, 16), memory: 6144 bytes
EFFICIENT shape: (48, 3)
💡Senior Shortcut:
When you need to flatten all spatial dimensions but keep channels separate, use data.reshape(data.shape[0], -1, data.shape[-1]).transpose(0,2,1) — one reshape, one trivial transpose, zero temporaries.
🎯 Key Takeaway
Avoid chaining transpose and reshape; combine into a single operation to halve memory allocations.
● Production incidentPOST-MORTEMseverity: high
Silent Corruption: How ravel() Sabotaged Training Data
Symptom
Model accuracy plateaued at 67% after adding a custom augmentation layer. No errors, just consistently poor convergence.
Assumption
flatten() and ravel() are interchangeable; since performance mattered, ravel() was used to minimize overhead.
Root cause
The augmentation pipeline produced a non-contiguous array (after transpose + slicing). ravel() returned a view that pointed to the same memory, but later in-place modifications in the model preprocessing (normalize) overwrote data that was still referenced by the augmentation cache. The view introduced unintended aliasing.
Fix
Replace ravel() with flatten().copy() in the data pipeline, or ensure the array is contiguous before calling ravel() using np.ascontiguousarray(). Added a unit test that checks array.flags.c_contiguous before allowing ravel() in production paths.
Key lesson
Never assume ravel() returns a view — it can, and when it does, mutations to the view affect the original.
In data pipelines where data integrity is critical, use flatten() or explicitly copy the array.
Always validate contiguity flags (arr.flags['C_CONTIGUOUS']) before using ravel() in shared-memory contexts.
Production debug guideSymptom → Action reference for common NumPy shape manipulation issues4 entries
Symptom · 01
ValueError: cannot reshape array of size 12 into shape (3,5)
→
Fix
Total elements must match. Check source array shape: arr.shape. Use -1 for the dimension you want NumPy to compute.
Symptom · 02
Unexpected mutation of original array after using reshape()
→
Fix
Check contiguity: arr.flags['C_CONTIGUOUS']. If True, reshape returned a view. Use .copy() if independent copy needed.
Symptom · 03
MemoryError when calling flatten() on a large array
→
Fix
flatten() always copies memory. For large arrays, consider ravel() if you don't need a separate copy, or use .reshape(-1) which may produce a view.
Symptom · 04
Broadcasting error — shapes (3,1) and (1,4) don't align for matrix multiplication
→
Fix
Reshape or transpose dimensions. Use reshape(3,4) or transpose to align axes. Check broadcasting rules: trailing dims must match or be 1.
★ Quick Shape Debug CommandsCommands to diagnose shape, memory layout, and contiguity issues
Need to verify memory layout before ravel/reshape−
Immediate action
Check contiguity flags
Commands
arr.flags['C_CONTIGUOUS']
arr.flags['F_CONTIGUOUS']
Fix now
If not contiguous, use np.ascontiguousarray(arr) then call ravel() or reshape().
Array shape doesn't match expectation after operation+
Immediate action
Print current shape
Commands
arr.shape
arr.ndim
Fix now
Use arr.reshape(-1, desired_cols) to let NumPy infer row count.
Combining reshape with Other Operations Without Intermediate
Key takeaways
1
reshape() returns a view when memory is contiguous
mutating the result mutates the original.
2
flatten() always copies; ravel() returns a view when possible.
3
transpose() and .T always return views
no data is copied.
4
Use -1 in reshape() as a wildcard to let NumPy compute one dimension automatically.
5
squeeze() and expand_dims() are how you fix mismatched shapes before broadcasting.
6
Always check arr.flags['C_CONTIGUOUS'] before relying on view semantics.
INTERVIEW PREP · PRACTICE MODE
Interview Questions on This Topic
Q01SENIOR
What is the difference between flatten() and ravel() in NumPy?
Q02SENIOR
When does reshape() return a view vs a copy?
Q03SENIOR
How does transpose affect memory layout and subsequent operations?
Q01 of 03SENIOR
What is the difference between flatten() and ravel() in NumPy?
ANSWER
flatten() always returns a copy of the array in 1D, allocating new memory. ravel() returns a flattened view when the array is contiguous in memory; if not contiguous, it returns a copy. Performance-wise, ravel() is faster and memory-efficient for contiguous arrays because it doesn't allocate new memory. Use flatten() when you need an independent copy that won't affect the original array.
Q02 of 03SENIOR
When does reshape() return a view vs a copy?
ANSWER
reshape() returns a view when the underlying data is contiguous in memory (C-order or Fortran-order). After operations like transpose, fancy indexing, or slicing, the array may become non-contiguous, in which case reshape() will return a copy. You can check contiguity with arr.flags['C_CONTIGUOUS']. If you need to guarantee a view, first make the array contiguous using np.ascontiguousarray(arr).
Q03 of 03SENIOR
How does transpose affect memory layout and subsequent operations?
ANSWER
transpose() always returns a view, so no data is copied. However, the resulting array is non-contiguous in memory (its strides are rearranged). This means subsequent operations like reshape() or flatten() may cause a copy because they require contiguity. Also, iterating over a transposed array is slower due to strided memory access. For performance-critical code, call np.ascontiguousarray() after transpose if you plan to do further reshaping or iteration.
01
What is the difference between flatten() and ravel() in NumPy?
SENIOR
02
When does reshape() return a view vs a copy?
SENIOR
03
How does transpose affect memory layout and subsequent operations?
SENIOR
FAQ · 4 QUESTIONS
Frequently Asked Questions
01
When does reshape() return a copy instead of a view?
When the array is not contiguous in memory — for example, after a transpose or certain fancy indexing operations. You can check with arr.flags['C_CONTIGUOUS']. If reshape cannot produce a view, it silently creates a copy.
Was this helpful?
02
What is the difference between shape (n,) and shape (1, n)?
Shape (n,) is a 1-D array. Shape (1, n) is a 2-D array with one row. They broadcast differently. Most NumPy operations accept both, but operations that expect a matrix (like dot product dimension rules) care about the distinction.
Was this helpful?
03
Is it safe to use ravel() in a multi-threaded environment?
If the array is contiguous, ravel() returns a view that shares memory. In multi-threaded code, if one thread modifies the raveled array and another reads the original, you'll get a data race. Use flatten() or explicitly copy to avoid shared state.
Was this helpful?
04
How can I avoid a copy when reshaping a transposed array?
First make the array contiguous with np.ascontiguousarray(arr), then reshape. However, this still copies if the array was non-contiguous. The only way to guarantee no copy is to reshape before transpose or design the data layout to be C-contiguous from the start.