Overloading Addition, Subtraction, and Multiplication Operators - python

How do you go about overloading the addition, subtraction, and multiplication operator so we can add, subtract, and multiply two vectors of different or identical sizes? For example, if the vectors are different sizes we must be able to add, subtract, or multiply the two vectors according to the smallest vector size?
I've created a function that allows you to modify different vectors, but now I'm struggling to overload the operators and haven't a clue on where to begin. I will paste the code below. Any ideas?
def __add__(self, y):
self.vector = []
for j in range(len(self.vector)):
self.vector.append(self.vector[j] + y.self.vector[j])
return Vec[self.vector]

You define the __add__, __sub__, and __mul__ methods for the class, that's how. Each method takes two objects (the operands of +/-/*) as arguments and is expected to return the result of the computation.

Nothing wrong with the accepted answer on this question but I'm adding some quick snippets to illustrate how this can be used. (Note that you could also "overload" the method to handle multiple types.)
"""Return the difference of another Transaction object, or another
class object that also has the `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other.val
buy = Transaction(10.00)
sell = Transaction(7.00)
print(buy - sell)
# 3.0
"""Return a Transaction object with `val` as the difference of this
Transaction.val property and another object with a `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return Transaction(self.val - other.val)
buy = Transaction(20.00)
sell = Transaction(5.00)
result = buy - sell
print(result.val)
# 15
"""Return difference of this Transaction.val property and an integer."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other
buy = Transaction(8.00)
print(buy - 6.00)
# 2

docs have the answer. Basically there are functions that get called on an object when you add or multiple, etc. for instance __add__ is the normal add function.

Related

How can I reduce redundancy by only defining the __add__ method only once?

class Ferrari:
def __init__(self,no_cars):
self.no_cars=no_cars
def __add__(self,other):
return self.no_cars+other.no_cars
class Jaquar:
def __init__(self,no_cars):
self.no_cars=no_cars
def __add__(self,other):
return self.no_cars+other.no_cars
f1=Ferrari(5)
j1=Jaquar(10)
total_cars= f1 + j1
print(total_cars)
I am trying to add two objects of different classes with operator overloading but it seems if I change the order of the operands, I will get an error that is why I have to define the __add__ method in both the classes so even if I change the order I will still get the same output but the code seems redundant and I cannot figure out any other way to do it. What can be the best alternative to it so my code is not redundant?
Define the __radd__ method, it handles the arguments being in the opposite order.
class Ferrari:
def __init__(self,no_cars):
self.no_cars=no_cars
def __add__(self,other):
return self.no_cars+other.no_cars
def __radd__(self, other):
return self + other

Special Values of a Class

Right now I am creating a class which represents a closed interval. Its core functionality is to provide an intersect method.
class Interval:
def __init__(self, a, b):
# check a <= b otherwise swap
self.a = a
self.b = b
def intersect(self, other):
a = self.a if self.a > other.a else other.a
b = self.b if self.b < other.b else other.b
if b < a:
# return some value representing an empty interval, providing the intersect method
return Intervall(a,b)
It should be possible to represent special Values like all points [-oo,oo] or the empty set {}. Which still serve the intersect method. My current approach is to create a new class, but this seems kinda tedious.
class EmptyInterval:
def intersect(self, other):
return self
Assuming those special values' intersect methods take precedence I'd prepend on the Intervall class' method:
class Intervall:
...
def intersect(self,other):
if not isinstance(self, other):
other.intersect(self)
...
To clarify - the following should be legal:
a = Intervall(1,2)
b = Intervall(3,4)
c = a.intersect(b) # resulting in an empty interval
c.intersect(a) # resulting again in an empty interval
Is there some elegant / more pythonic / less nauseating ugly way to implement such a behavior?
First I thought of inheritance, but that seems quite unfitting because of the precedence those special values should have; i.e. I do not know how to implement it via inheritance.
Define a couple special functions in your class Interval:
#staticmethod
def everything():
return Interval(-math.inf, math.inf)
#staticmethod
def nothing():
return Interval(math.nan, math.nan)
You may find it more natural to write nothing() like this:
return Interval(0, 0)
or this:
return Interval(math.inf, math.inf)
It rather depends on your other code, and what you think is the most natural way to represent the empty interval. Note that any less or greater comparison with NAN will return false, so this may have some impact on which way you decide to represent the empty interval (for example is nothing().intersect(nothing()) supposed to be true or false?).
Maybe this could be another solution:
Instead of passing a,b separately, I could pass a tuple (a,b). Further I could declare a couple of singletons as class variables. During instantiation I'd pass that singleton and would only have to check whether that value is one of the singletons and act accordingly.
class Interval:
EMPTY = object()
EVERYTHING = object()
def __init__(self, bounds):
self.bound = bounds
def intersect(self, other):
if self.bounds == self.EMPTY or other.bounds == self.EMPTY:
return Interval(self.EMPTY)
...
if b < a:
return Interval(self.EMPTY)
return Interval((a,b))
I guess this maybe less error prone than John's answer, because of the general behavior math.inf and / or math.nan impose. Also it would allow to strictly forbid those values to be passed, as Interval(math.nan, 1) would be nonsensical.
But it may be more effort to implement in a more complex setting.

How to add 2 instances of 2 different classes [duplicate]

How do you go about overloading the addition, subtraction, and multiplication operator so we can add, subtract, and multiply two vectors of different or identical sizes? For example, if the vectors are different sizes we must be able to add, subtract, or multiply the two vectors according to the smallest vector size?
I've created a function that allows you to modify different vectors, but now I'm struggling to overload the operators and haven't a clue on where to begin. I will paste the code below. Any ideas?
def __add__(self, y):
self.vector = []
for j in range(len(self.vector)):
self.vector.append(self.vector[j] + y.self.vector[j])
return Vec[self.vector]
You define the __add__, __sub__, and __mul__ methods for the class, that's how. Each method takes two objects (the operands of +/-/*) as arguments and is expected to return the result of the computation.
Nothing wrong with the accepted answer on this question but I'm adding some quick snippets to illustrate how this can be used. (Note that you could also "overload" the method to handle multiple types.)
"""Return the difference of another Transaction object, or another
class object that also has the `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other.val
buy = Transaction(10.00)
sell = Transaction(7.00)
print(buy - sell)
# 3.0
"""Return a Transaction object with `val` as the difference of this
Transaction.val property and another object with a `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return Transaction(self.val - other.val)
buy = Transaction(20.00)
sell = Transaction(5.00)
result = buy - sell
print(result.val)
# 15
"""Return difference of this Transaction.val property and an integer."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other
buy = Transaction(8.00)
print(buy - 6.00)
# 2
docs have the answer. Basically there are functions that get called on an object when you add or multiple, etc. for instance __add__ is the normal add function.

Implicit conversions in Python

For example, if I wanted to apply mathematical operations on objects in the following way:
class A(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return value
assert(A(1) + A(2) == 3)
I am getting the following error: TypeError: unsupported operand type(s) for +: 'A' and 'A'
Is it possible to evaluate objects to primitives so that I can apply simple operations on them? Similarly how you could use implicit conversions in Scala.
You can implement __add__ to define addition on your class.
class A(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return 'A(%r)'%self.value
def __add__(self, other):
return A(self.value+other.value)
>>> A(1)+A(2)
A(3)
This implementation assumes that you are only trying to add instances of A to other instances of A to get a third instance of A. You can write an __add__ adaptable to what type of operand you need it to work for.
See also __radd__ and __iadd__.
That depends on what you're trying to do. You can define the + operator by defining the __add__ method:
class A(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return value
def __add__(self, other):
return A(self.value + other.value)
then of course in your example code you're trying to compare it to an integer which also need to be defined - which is done by implementing the __eq__ method:
def __eq__(self, other):
try:
self.value == other.value
except AttributeError: # other wasn't of class A, try to compare directly instead
return self.value == other
(implicit typecasts on the other hand is not available as far as I know)
The problem is that there isn't enough context in the expression to decide what the objects should be converted to. Python has various methods that can be defined on an object that implement various operators, including the __add__() and __radd__() methods.
There isn't enough context to know that foo should be equivalent to foo.value, so with Python's philosophy explicit is better than implicit. You can certainly subclass int, but then the operators won't produce your new class, and the object itself would remain immutable (as numbers in Python generally are). Notably, ctypes such as c_int32 have a value attribute like your example but do not implement numeric operators.

python class Vector, change from 3dimension to ndimension

I made this class that computes some operations for 3d vectors, is there anyway I can change the code so that it computes the same operations but for vectors of any dimension n?
import sys
class Vector:
def __init__(self,x,y,z):
self.x= x
self.y= y
self.z= z
def __repr__(self):
return "(%f,%f,%f)"%(self.x,self.y,self.z)
def __add__(self,other):
return (self.x+other.x,self.y+other.y,self.z+other.z)
def __sub__(self,other):
return (self.x-other.x,self.y-other.y,self.z-other.z)
def __norm__(self):
return (self.x**2+self.y**2+self.z**2)**0.5
def escalar(self,other):
return (self.x*other.x+self.y*other.y+self.z*other.z)
def __mod__(self,other):
return (self.x%other.x,self.y%other.y,self.z%other.z)
def __neg__(self):
return (-self.x,-self.y,-self.z)
As an example, for a n dimensional vector, something like
class Vector:
def __init__(self, components):
self.components = components # components should be a list
def __add__(self, other):
assert len(other.components) == len(self.components)
added_components = []
for i in range(len(self.components)):
added_components.append(self.components[i] + other.components[i])
return Vector(added_components)
def dimensions(self):
return len(self.components)
would be possible. Note that the __add__ override returns a new Vector instance, not a tuple as in your case. Then adapt your other methods likewise.
There are more 'clever' ways of adding elements from two lists, into a third. You should really not do it this way if performance is an issue though (or in any other case but an exercise, IMO). Look into numpy.
Use a list to store the coefficients rather than explicit variables. For negating, adding, subtracting etc. you just iterate over the lists.
In terms of initialisation, you need to use *args for the input. Have a look at this post for an explanation of how it works: https://stackoverflow.com/a/3394898/1178052

Categories

Resources