ZetCode

Python __isub__ Method

Last modified April 8, 2025

This comprehensive guide explores Python's __isub__ method, the special method for in-place subtraction. We'll cover basic usage, operator overloading, mutable vs immutable types, and practical examples.

Basic Definitions

The __isub__ method implements the in-place subtraction operation (-=). It modifies the object's value without creating a new object.

Key characteristics: it should modify and return self, is called when -= is used, and typically provides better performance than regular subtraction for mutable objects.

Basic __isub__ Implementation

Here's a simple implementation showing how __isub__ works with a custom class. The method modifies the instance in place.

basic_isub.py
class Counter:
 def __init__(self, value):
 self.value = value
 
 def __isub__(self, other):
 self.value -= other
 return self
 
 def __repr__(self):
 return f"Counter({self.value})"
c = Counter(10)
c -= 3
print(c) # Counter(7)

This example shows a simple counter class that implements in-place subtraction. When -= is used, __isub__ modifies the instance's value and returns self.

The method must return self to work correctly with chained operations and to match Python's expected behavior for in-place operations.

__isub__ with Mutable Objects

For mutable objects, __isub__ can provide significant performance benefits by avoiding the creation of new objects during subtraction.

mutable_isub.py
class Vector:
 def __init__(self, x, y):
 self.x = x
 self.y = y
 
 def __isub__(self, other):
 self.x -= other.x
 self.y -= other.y
 return self
 
 def __repr__(self):
 return f"Vector({self.x}, {self.y})"
v1 = Vector(5, 7)
v2 = Vector(2, 3)
v1 -= v2
print(v1) # Vector(3, 4)

This vector class implements in-place vector subtraction. The operation modifies the original vector instead of creating a new one, which is more efficient.

For large objects or frequent operations, this can significantly reduce memory usage and improve performance compared to regular subtraction.

__isub__ with Immutable Objects

Immutable objects can't be modified in place, so their __isub__ typically returns a new object, similar to regular subtraction.

immutable_isub.py
class ImmutablePoint:
 def __init__(self, x, y):
 self._x = x
 self._y = y
 
 @property
 def x(self):
 return self._x
 
 @property
 def y(self):
 return self._y
 
 def __isub__(self, other):
 return ImmutablePoint(self.x - other, self.y - other)
 
 def __repr__(self):
 return f"Point({self.x}, {self.y})"
p = ImmutablePoint(8, 6)
p -= 2
print(p) # Point(6, 4)

This immutable point class returns a new instance when __isub__ is called. The original object remains unchanged, maintaining immutability.

Note that for immutable objects, a -= b behaves the same as a = a - b, just with potentially different implementation details.

__isub__ with Different Types

__isub__ can handle operations with different types, providing flexible in-place subtraction behavior.

type_handling_isub.py
class Measurement:
 def __init__(self, value, unit='m'):
 self.value = value
 self.unit = unit
 
 def __isub__(self, other):
 if isinstance(other, (int, float)):
 return Measurement(self.value - other, self.unit)
 elif isinstance(other, Measurement):
 if self.unit == other.unit:
 return Measurement(self.value - other.value, self.unit)
 raise ValueError("Units must match")
 raise TypeError("Unsupported type")
 
 def __repr__(self):
 return f"{self.value}{self.unit}"
m = Measurement(10)
m -= 2.5
print(m) # 7.5m

This measurement class handles subtraction with both numbers and other measurements. It includes unit checking when subtracting measurements.

The implementation shows how to make __isub__ work with multiple types while maintaining proper error checking and type safety.

__isub__ in Built-in Types

Python's built-in types like lists implement __isub__ for in-place operations. Here's how it works with lists.

builtin_isub.py
numbers = [1, 2, 3, 4, 5]
numbers -= [3, 4] # Equivalent to numbers.extend([3, 4])
print(numbers) # [1, 2, 3, 4, 5, 3, 4]
# For sets, -= performs difference_update
s = {1, 2, 3, 4, 5}
s -= {3, 4}
print(s) # {1, 2, 5}

For lists, -= performs an extend operation (which might be surprising). For sets, it performs a difference update, removing elements.

This demonstrates how different built-in types implement __isub__ differently based on their semantics. Always check the type's documentation.

Best Practices

  • Return self: For mutable objects, modify and return self
  • Handle types properly: Check types and raise appropriate errors
  • Maintain immutability: For immutable objects, return new instances
  • Document behavior: Clearly document what -= does for your class
  • Consider performance: Use in-place ops for better performance with mutable objects

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.

AltStyle によって変換されたページ (->オリジナル) /