Python __neg__ Method
Last modified April 8, 2025
This comprehensive guide explores Python's __neg__ method, the
special method that implements the unary negation operator (-). We'll cover
basic usage, mathematical operations, custom classes, and practical examples.
Basic Definitions
The __neg__ method is a special method in Python that implements
the unary negation operator (-). When you use the - operator on an object,
Python calls this method to determine the result.
Key characteristics: it takes only self as parameter, returns the
negated value, and should return a new object rather than modifying the
original. It enables operator overloading for custom classes.
Basic __neg__ Implementation
Here's a simple implementation showing how __neg__ works with a
custom number class. It demonstrates the basic syntax and behavior.
class Number:
def __init__(self, value):
self.value = value
def __neg__(self):
return Number(-self.value)
def __repr__(self):
return f"Number({self.value})"
num = Number(5)
neg_num = -num
print(neg_num) # Output: Number(-5)
This example shows that applying the - operator to a Number instance calls
__neg__, which returns a new Number with the negated value.
The original object remains unchanged.
The __repr__ method is included for better string representation
but isn't required for __neg__ functionality.
Mathematical Vector Negation
The __neg__ method is particularly useful for mathematical
classes where negation has a specific meaning, like vectors.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __neg__(self):
return Vector(-self.x, -self.y)
def __repr__(self):
return f"Vector({self.x}, {self.y})"
v = Vector(3, -4)
neg_v = -v
print(neg_v) # Output: Vector(-3, 4)
In this vector example, negation returns a new vector with both components negated. This follows standard mathematical vector negation rules.
The method preserves the original vector while creating a new one with the negated values, which is the expected behavior for immutable objects.
Temperature Class with Negation
Here's a practical example using __neg__ with a temperature
class that handles both Celsius and Fahrenheit scales.
class Temperature:
def __init__(self, value, scale='C'):
self.value = value
self.scale = scale
def __neg__(self):
return Temperature(-self.value, self.scale)
def convert(self):
if self.scale == 'C':
return Temperature(self.value * 9/5 + 32, 'F')
else:
return Temperature((self.value - 32) * 5/9, 'C')
def __repr__(self):
return f"{self.value}°{self.scale}"
temp = Temperature(25)
print(-temp) # Output: -25°C
print((-temp).convert()) # Output: -13.0°F
This temperature class demonstrates that __neg__ only negates the
value while preserving the scale. The conversion method shows how negation
interacts with other operations.
Note that the negation doesn't automatically convert between scales - it simply negates the numerical value in the current scale.
Custom Money Class with Negation
This example shows a Money class where negation represents debt or negative balance, a common financial concept.
class Money:
def __init__(self, amount, currency='USD'):
self.amount = amount
self.currency = currency
def __neg__(self):
return Money(-self.amount, self.currency)
def __add__(self, other):
if self.currency != other.currency:
raise ValueError("Currencies must match")
return Money(self.amount + other.amount, self.currency)
def __repr__(self):
return f"{self.amount:.2f} {self.currency}"
balance = Money(100.50)
debt = -balance
print(debt) # Output: -100.50 USD
print(balance + debt) # Output: 0.00 USD
In this financial context, negation represents a debt or negative balance. The example also shows how negation interacts with addition to zero out a balance.
The currency check in __add__ demonstrates that __neg__
preserves all attributes (like currency) while only negating the amount.
Matrix Negation
For more complex mathematical objects like matrices, __neg__
can implement element-wise negation following linear algebra rules.
class Matrix:
def __init__(self, data):
self.data = data
def __neg__(self):
neg_data = [[-elem for elem in row] for row in self.data]
return Matrix(neg_data)
def __repr__(self):
return '\n'.join(' '.join(f"{elem:3}" for elem in row)
for row in self.data)
m = Matrix([[1, 2], [3, 4]])
print("Original:")
print(m)
print("\nNegated:")
print(-m)
This matrix implementation shows how __neg__ can handle nested
data structures by applying the negation operation to each element.
The list comprehension creates a new matrix with all elements negated, following mathematical matrix negation rules while preserving the structure.
Best Practices
- Return a new object: Negation should not modify the original
- Preserve other attributes: Only negate what's mathematically appropriate
- Maintain immutability: Original object should remain unchanged
- Type consistency: Return the same type as the original
- Document behavior: Clearly explain what negation means for your class
Source References
Author
List all Python tutorials.