In-Place Operations¶
In-place operations modify arrays without creating new memory allocations.
Core Concept¶
In-place operations reduce memory footprint and improve cache efficiency.
1. Standard Operation¶
import numpy as np
arr = np.array([1, 2, 3, 4])
arr = arr * 2 # Creates new array, rebinds name
2. In-Place Operation¶
import numpy as np
arr = np.array([1, 2, 3, 4])
arr *= 2 # Modifies array in place
3. Memory Difference¶
Standard creates temporary; in-place modifies existing memory.
Augmented Assignment¶
Python's augmented assignment operators perform in-place operations.
1. Arithmetic In-Place¶
import numpy as np
arr = np.array([1, 2, 3, 4], dtype=float)
arr += 10 # Add
arr -= 5 # Subtract
arr *= 2 # Multiply
arr /= 4 # Divide
arr **= 2 # Power
arr //= 3 # Floor divide
arr %= 2 # Modulo
print(arr)
2. Bitwise In-Place¶
import numpy as np
arr = np.array([1, 2, 3, 4], dtype=int)
arr &= 3 # AND
arr |= 8 # OR
arr ^= 1 # XOR
Memory Verification¶
Verify that in-place operations don't create new arrays.
1. id() Check¶
import numpy as np
def main():
arr = np.array([1, 2, 3, 4])
original_id = id(arr)
arr *= 2
print(f"ID unchanged: {id(arr) == original_id}")
if __name__ == "__main__":
main()
Output:
ID unchanged: True
2. Standard Creates New¶
import numpy as np
def main():
arr = np.array([1, 2, 3, 4])
original_id = id(arr)
arr = arr * 2
print(f"ID unchanged: {id(arr) == original_id}")
if __name__ == "__main__":
main()
Output:
ID unchanged: False
out Parameter¶
Many NumPy functions support an out parameter for in-place results.
1. Using out¶
import numpy as np
def main():
a = np.array([1, 2, 3, 4])
result = np.empty_like(a)
np.multiply(a, 2, out=result)
print(result)
if __name__ == "__main__":
main()
2. Same Array out¶
import numpy as np
def main():
arr = np.array([1, 2, 3, 4])
np.multiply(arr, 2, out=arr)
print(arr)
if __name__ == "__main__":
main()
Output:
[2 4 6 8]
3. Chained Operations¶
import numpy as np
def main():
arr = np.array([1.0, 2.0, 3.0, 4.0])
np.sqrt(arr, out=arr)
np.multiply(arr, 10, out=arr)
print(arr)
if __name__ == "__main__":
main()
Performance Benefit¶
In-place operations improve performance for large arrays.
1. Timing Comparison¶
import numpy as np
import time
def main():
n = 10_000_000
# Standard operation
arr1 = np.random.randn(n)
start = time.perf_counter()
arr1 = arr1 * 2
standard_time = time.perf_counter() - start
# In-place operation
arr2 = np.random.randn(n)
start = time.perf_counter()
arr2 *= 2
inplace_time = time.perf_counter() - start
print(f"Standard time: {standard_time:.4f} sec")
print(f"In-place time: {inplace_time:.4f} sec")
if __name__ == "__main__":
main()
2. Cache Efficiency¶
In-place avoids cache eviction from temporary allocations.
Caveats¶
Be aware of in-place operation limitations.
1. View Side Effects¶
import numpy as np
arr = np.array([1, 2, 3, 4])
view = arr[1:3]
view *= 10
print(arr) # [1 20 30 4]
2. dtype Constraints¶
In-place operations cannot change dtype.
3. Broadcasting Limit¶
In-place requires compatible shapes without expansion.