Complete guide to Python's __neg__ method covering unary operator overloading, mathematical operations, and custom classes.
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.
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.
Here’s a simple implementation showing how neg works with a custom number class. It demonstrates the basic syntax and behavior.
basic_neg.py
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.
The neg method is particularly useful for mathematical classes where negation has a specific meaning, like vectors.
vector_negation.py
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.
Here’s a practical example using neg with a temperature class that handles both Celsius and Fahrenheit scales.
temperature_negation.py
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.
This example shows a Money class where negation represents debt or negative balance, a common financial concept.
money_negation.py
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.
For more complex mathematical objects like matrices, neg can implement element-wise negation following linear algebra rules.
matrix_negation.py
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.
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
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.