How to add two instances of my custom class - python

I want to run this code (must) including the attribute value next to total in the print section. What code should I insert inside the class to do it?
class Random:
def __init__(self, x):
self.x = x
def __add__(self, other):
return self.x + other.x
p1 = Random(2)
p2 = Random(3)
total = p1 + p2
print(total.value)

Return an instance of Random in your __add__ method and add a property with the name value for the class.
class Random:
def __init__(self, x):
self.x = x
def __add__(self, other):
return Random(self.x + other.x)
#property
def value(self):
return self.x
p1 = Random(2)
p2 = Random(3)
total = p1 + p2
print(total.value)
Of course the better option would be to replace the instance attribute x with value. Then there's no need for the property.
class Random:
def __init__(self, x):
self.value = x
def __add__(self, other):
return Random(self.value + other.value)

Make total a Random as well.
class Random:
def __init__(self, value):
self.value = value
def __add__(self, other):
return Random(self.value + other.value)
p1: Random = Random(2)
p2: Random = Random(3)
total: Random = p1 + p2
print(total.value)

Related

Not iterable object in python

I am trying to write a function that returns the variables contained in a class of type Rule. I need to iterate through it and get all variables and store them in a set.
class Rule:
# head is a function
# body is a *list* of functions
def __init__(self, head, body):
self.head = head
self.body = body
def __str__(self):
return str(self.head) + ' :- ' + str(self.body)
def __eq__(self, other):
if not isinstance(other, Rule):
return NotImplemented
return self.head == other.head and self.body == other.body
def __hash__(self):
return hash(self.head) + hash(self.body)
class RuleBody:
def __init__(self, terms):
assert isinstance(terms, list)
self.terms = terms
def separator(self):
return ','
def __str__(self):
return '(' + (self.separator() + ' ').join(
list(map(str, self.terms))) + ')'
def __eq__(self, other):
if not isinstance(other, RuleBody):
return NotImplemented
return self.terms == other.terms
def __hash__(self):
return hash(self.terms)
My function is the following:
def variables_of_clause (self, c : Rule) -> set :
returnSet = set()
l = getattr(c, 'body')
for o in l:
returnSet.add(o)
Testing function
# The variables in a Prolog rule p (X, Y, a) :- q (a, b, a) is [X; Y]
def test_variables_of_clause (self):
c = Rule (Function ("p", [Variable("X"), Variable("Y"), Atom("a")]),
RuleBody ([Function ("q", [Atom("a"), Atom("b"), Atom("a")])]))
#assert
(self.variables_of_clause(c) == set([Variable("X"), Variable("Y")]))
I keep getting an error that says: TypeError: 'RuleBody' is not iterable.
RuleBody.terms is a list, not RuleBody, you can iterate over RuleBody.terms instead, however, you can make your RuleBody class iterable (by basically making it return RuleBody.terms's elements), using the __iter__ method:
class RuleBody:
... # everything
...
def __iter__(self):
return iter(self.terms)

How to update classes

class Dog(object):
def __init__(self, number):
self.number = number
def number_update(self):
self.number += 1
class Cat(object):
def __init__(self, number):
self.number = number
class1 = Dog(1)
class2 = Cat(class1.number * 0.5)
class1.number_update()
print(class1.number)
print(class2.number)
Current output: 2, 0.5
I want: 2, 1
I really simplified it, so I hope you will understand
Thank you for help
You are running class1.number_update() after you define the class2 variable, so the class1 variable has a value of 1 when you define class2, and after you define class2, class1 becomes into 2. To fix this, just switch around those two lines:
class Dog(object):
def __init__(self, number):
self.number = number
def number_update(self):
self.number += 1
class Cat(object):
def __init__(self, number):
self.number = number
class1 = Dog(1)
class1.number_update()
class2 = Cat(class1.number * 0.5)
print(class1.number)
print(class2.number)
You could return the number in number_update():
class Dog(object):
def __init__(self, number):
self.number = number
def number_update(self):
self.number += 1
return self.number
class Cat(object):
def __init__(self, number):
self.number = number
class1 = Dog(1)
class2 = Cat(class1.number_update() * .5)
print(class1.number)
print(class2.number)
Output:
2
1.0
As suggested in the comments, to do this exactly as you want, you'll have to write your own expression and number classes, such as this:
class Op:
def __init__(self, op):
self.op = op
def __call__(self, a, b):
if self.op == "*":
return a * b
if self.op == "/":
return a / b
if self.op == "-":
return a - b
if self.op == "+":
return a + b
raise TypeError(f"Unknown op {repr(self.op)}")
def __repr__(self):
return self.op
mul = Op("*")
div = Op("/")
add = Op("+")
sub = Op("-")
class Expr:
def __init__(self, a, b, op):
self.op = op
self.a = a
self.b = b
def eval(self):
return self.op(self.a.eval(), self.b.eval())
def __repr__(self):
return f"({self.a} {self.op} {self.b})"
def __mul__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, mul)
def __div__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, div)
def __add__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, add)
def __sub__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, sub)
def __rmul__(self, other):
return self.__class__.__mul__(other, self)
def __rdiv__(self, other):
return self.__class__.__div__(other, self)
def __rsub__(self, other):
return self.__class__.__sub__(other, self)
def __radd__(self, other):
return self.__class__.__add__(other, self)
class Number(Expr):
def __init__(self, value):
self._value = value
def get(self):
return self._value
def set(self, new):
self._value = new
def increment(self):
self._value += 1
def eval(self):
return self._value
def __repr__(self):
return str(self._value)
class Dog:
def __init__(self, number):
self.number = Number(number)
def number_update(self):
self.number.increment()
class Cat:
def __init__(self, number):
self._number = number
#property
def number(self):
return self._number.eval()
#number.setter
def number(self, new):
if isinstance(new, (int, float)):
new = Number(new)
self._number = new
cls1 = Dog(1)
cls2 = Cat(cls1.number * 0.5)
cls1.number_update()
print(cls1.number)
print(cls2.number)
Here, we get the expected output of
2
1.0
Lets go through the lines of your main function and trace the values of Dog and Cat
class1 = Dog(1) # Dog=1; Cat=undefined
class2 = Cat(class1.number * 0.5) # Dog=1; Cat=1*0.5=0.5
class1.number_update() # Dog=2; Cat=0.5
print(class1.number) # >>>"2"
print(class2.number) # >>>"0.5"
Your class doesn't have a reference to Dog's number member, it just references the Cat class property.
EDIT: It doesn't copy, it creates a reference directly to the object.

How to perform value check inside class

So the task is to make a universal Vector class to perform add method whatever(str or int) the x,y values are.
So here is the code that i've tried to execute just to check if try,except somehow works inside a class
class Vector():
def __init__(self,x,y):
self.x = x
self.y = y
def __valuecheck__(self):
try:
self.x + "a"
except TypeError:
return str(self.x)
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __repr__(self):
return "Vector({},{})".format(self.x,self.y)
a = Vector(1,"a")
b = Vector("a",2)
c = a.__add__(b)
print(c)
The expected output is
Vector(1a,a2)
I've tried different variants, defining classic function e.g. def valuecheck(), as well tried adding try,except to add and init method, but none seem to work. Need your help guys, any tip is very appreciated!
Cheers!
I think I have found the answer.
class Vector():
def __init__(self,x,y):
self.x = x
self.y = y
def __valuecheck__(self):
try:
self.x + "a"
except TypeError:
return str(self.x)
def __repr__(self):
return "Vector({},{})".format(self.x,self.y)
def __add__(self, other):
mvbh = str(self.x), str(self.y) # My Vector Before Hand
myVector = ''.join(mvbh)
ovbh = str(other.x), str(other.y) # Other Vector Before Hand
otherVector = ''.join(ovbh)
final = "Vector({}, {})".format(myVector, otherVector) # Change this to create a new vector
print(final)
a = Vector(1,"a")
b = Vector("a",2)
a.__add__(b)
class Vector():
def __init__(self,x,y):
self.x = x
self.y = y
def __valuecheck__(self):
try:
self.x + "a"
except TypeError:
return str(self.x)
def __add__(self, other):
return Vector(str(self.x) + str(other.x), str(self.y) + str(other.y))
def __repr__(self):
return "Vector({},{})".format(self.x,self.y)
a = Vector(1,"a")
b = Vector("a",2)
c = a.__add__(b)
print(c)

How can i implement __add__ method in parent class?

I have object-oriented programming modelling for geometric shapes. I have add method in each classes if i want to add up two geometric shapes but I have defined in each subclass.
How can i implement the add method in the parent class , so that i don't to defined it for every subclasses?
import numpy as np
class Shape(object):
def __repr__(self):
return type(self).__name__
def __str__(self):
return type(self).__name__
class Circle(Shape):
"""
"""
# constructor
def __init__(self, radius):
self.radius = radius
def __add__(self, other):
if type(other) == int:
self.radius = self.radius + other
else:
newRadius = self.radius + other.radius
return Circle(newRadius)
def __radd__(self, other):
return self.__add__(other)
def area(self):
return np.pi * self.radius**2
class Rectangle(Shape):
# constructor
def __init__(self, width,height):
self.width , self.height = width, height
def __add__(self, other):
if type(other) == int:
self.width = self.width + other
self.height = self.height + other
else:
newWidth = self.width + other.width
newHeight = self.Height + other.Height
return Rectangle(newWidth,newHeight)
def __radd__(self, other):
return self.__add__(other)
def area(self):
"""
Function to compute the area of triangle.
"""
return self.width * self.height
This is a strange question, because it doesn't really make sense to add two circles and have the result be a new circle with the sum of the radiuses. You also have odd behaviour for adding with an int because you are changing the state of the object instead of creating a new one, like you do when adding an object.
But there is in fact a way to do this with just one method in the parent class, using some Python-specific features:
cls = self.__class__ is the class of the current object, which can be used to create a new object of the same class, and test if other is the right type.
d = self.__dict__ is a dictionary of the object's attributes.
The **{ ... } unpacking operator allows calling the cls constructor using a dictionary comprehension to compute the arguments.
I've also written a generic __repr__ which shows the state of the object, for conveniently testing examples in the REPL.
Here's an example:
class Shape:
def __add__(self, other):
cls = self.__class__
d = self.__dict__
if isinstance(other, int):
return cls(**{ k: v + other for k, v in d.items() })
elif isinstance(other, cls):
return cls(**{ k: v + other.__dict__[k] for k, v in d.items() })
else:
raise TypeError()
def __radd__(self, other):
return self.__add__(other)
def __repr__(self):
d = self.__dict__
return '{0}({1})'.format(
self.__class__.__name__,
', '.join('{0}={1!r}'.format(k, v) for k, v in d.items())
)
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
class Rectangle(Shape):
def __init__(self, width, height):
self.width, self.height = width, height
Examples:
>>> Circle(4) + Circle(5)
Circle(radius=9)
>>> Circle(6) + 2
Circle(radius=8)
>>> 3 + Circle(2)
Circle(radius=5)
>>> Rectangle(2, 3) + Rectangle(4, 5)
Rectangle(width=6, height=8)
>>> Rectangle(2, 3) + 1
Rectangle(width=3, height=4)
>>> 5 + Rectangle(2, 3)
Rectangle(width=7, height=8)
Note that I've changed the behaviour to always return a new object, instead of mutating the existing one.

Make __add__ to return arithmetic mean

I want the add method of my object Foo to return averaged summation. For the summation of just two objects it is straightforward:
class Foo():
def __init__(self, n):
self.n = n
def __add__(self, other):
return Foo((self.n + other.n)/2)
How to do this for N>2 objects? E.g. Foo(0) + Foo(1) + Foo(2) + Foo(3) should return Foo((0 + 1 + 2 + 3)/4), i.e. Foo(1.5).
========================================
Edit: Here's my solution
class Foo():
def __init__(self, n):
self.n = n
self._n = n
self._count = 1
def __add__(self, other):
out = Foo(self._n + other._n)
out._count = self._count + other._count
out.n = out.n/out._count
return out
Not the best way to get the arithmetic mean, but I needed to do it in this way. Also, this demonstrates how to do special additions of user defined objects, which return a function of the total sum of the objects. E.g. make __add__ return the square root of the sum of the objects:
class Bar():
def __init__(self, n):
self.n = n
self._n = n
def __add__(self, other):
out = Bar(self._n + other._n)
out.n = (out.n)**0.5
return out
One solution could be storing in the class TWO numbers: the average value and the number of samples:
class Foo:
def __init__(self, avg, count=1):
self.avg = avg
self.count = count
def __add__(self, other):
return Foo((self.avg*self.count + other.avg*other.count)
/
(self.count + other.count),
self.count + other.count)
Even better would be just storing the sum and compute the average only if/when requested.

Categories