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.
Related
Error:
TypeError: Fraction.__str__() missing 1 required positional argument: 'self'
Code:
class Fraction:
def __init__(self, numerator, denominator):
self.n = numerator
self.d = denominator
def __str__(self):
return f'{self.n}/{self.d}'
__repr__ = __str__()
def __add__(self, other): # adding the numbers
n = self.n * other.d + self.d * other.n
d = self.d * other.d
return Fraction(n, d) # object at 0x000001F5E5E6BEB0 memory of the location object
You are trying to call __str__ and assign its return value to __repr__. You want to assign the function itself:
__repr__ = __str__
However, __repr__ should usually return something resembling Python code that could be used to reconstruct the value, not necessarily the same value as __str__. Consider this instead:
class Fraction:
def __init__(self, numerator, denominator):
self.n = numerator
self.d = denominator
def __str__(self):
return f'{self.n}/{self.d}'
def __repr__(self):
return f'Fraction({self.n}, {self.d})'
def __add__(self, other):
n = self.n * other.d + self.d * other.n
d = self.d * other.d
return Fraction(n, d)
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)
class Math:
def __init__(self, number):
self.number = number
def add(self, add_num):
return self.number + add_num
def sub(self, sub_num):
return self.number - sub_num
Math(5).add(5)
I get 10 as expected
But if I do Math(5).add(5).sub(3):
I get this error AttributeError: 'int' object has no attribute 'sub'
for that to work your mehtods need to return self (or a fresh instance of Math):
class Math:
def __init__(self, number):
self.number = number
def add(self, add_num):
self.number += add_num
return self
# or:
# return Math(self.number + add_num)
def sub(self, sub_num):
self.number -= sub_num
return self
# or:
# return Math(self.number - add_num)
def __str__(self):
return str(self.number)
m = Math(5).add(5).sub(3)
print(m)
# 7
the add here now behaves more like an __iadd__.
Of course.
What you do is essentially
a = Math(5) # a is a "Math" object
b = a.add(5) # b is what add() returns, i. e. an int
c = b.sub(3) # an int has no sub() method
I don't know what exactly you want to achieve: do you want add() and sub() to modify the object you are operating on? In this case, you can do
class Math:
def __init__(self, number):
self.number = number
def add(self, add_num):
self.number = self.number + add_num
return self
def sub(self, sub_num):
self.number = self.number - sub_num
return self
If you don't want that, you can do instead
class Math:
def __init__(self, number):
self.number = number
def add(self, add_num):
return Math(self.number + add_num)
def sub(self, sub_num):
return Math(self.number - sub_num)
return self
In both cases, your intended way of chaining the calls works.
The value that you return is not an object of your Math class.
You must create an object of Math whose number attribute is your computed results and return that for your code to work.
When you execute return self.number + add_num, you return an integer, not an instance of your Math class. To solve this, you can change your add method to
return Math(self.number + add_num).
I am trying to override the __iadd__ method in python with fractions, now this is what I did. Please could some one check to see if I did it right. I have this and this, but that's not what I want. It should be used from a class perspective.
My __iadd__ code:
def __iadd__(self, other):
"""
Implementation of the '+='
augmented function
:param other:
:return:
"""
newnum = self.num * other.den + self.den * other.num
newden = self.den * other.den
v = Fraction(newnum, newden)
return v
This is done in a class Fractionwith this structure:
def gcd(m, n):
while m % n != 0:
oldm = m
oldn = n
m = oldn
n = oldm % oldn
return n
class Fraction:
# initializing variables for class
def __init__(self, top, bottom):
# check if entered fraction is an integer
if isinstance(top, int) and isinstance(bottom, int):
# reduce the given fractions to lowest term
common = gcd(top, bottom)
self.num = abs(top) // common
self.den = abs(bottom) // common
else:
raise "Please only integers are allowed"
def __str__(self):
return str(self.num) + "/" + str(self.den)
This actually return the write value when done like this:
f1 = Fraction(1, 2)
f2 = Fraction(8, 10)
f1 += f2
print(f1)
Also did it by calling an overridden __add__ method:
def __iadd__(self, other):
"""
Implementation of the '+='
augmented function
:param other:
:return:
"""
if other == 0:
return self
else:
return self.__add__(other)
The overridden __add__:
def __add__(self, otherfraction):
newnum = self.num * otherfraction.den + self.den * otherfraction.num
newden = self.den * otherfraction.den
return Fraction(newnum, newden)
Use __iadd__ to increment in-place.
Use __add__ to increment and create a new instance.
So, you can change your code as follow.
def __iadd__(self, other):
self.num = self.num * other.den + self.den * other.num
self.den = self.den * other.den
return self
See also this question: implementing add and iadd for custom class in python?
Note that Python has a Rational numbers module. Check the source codeā¦ But Fraction objects are immutable, so __iadd__ is not implemented.
I want to write a program that accepts as input a number p and produces as output a type-constructor for a number that obeys integer arithmetic modulo p.
So far I have
def IntegersModP(p):
N = type('IntegersMod%d' % p, (), {})
def __init__(self, x): self.val = x % p
def __add__(a, b): return N(a.val + b.val)
... (more functions) ...
attrs = {'__init__': __init__, '__add__': __add__, ... }
for name, f in attrs.items():
setattr(N, name, f)
return N
This works fine, but I'd like to know what the Pythonic way to do this is, which I understand would use metaclasses.
Like this:
def IntegerModP(p): # class factory function
class IntegerModP(object):
def __init__(self, x):
self.val = x % p
def __add__(a, b):
return IntegerModP(a.val + b.val)
def __str__(self):
return str(self.val)
def __repr__(self):
return '{}({})'.format(self.__class__.__name__, self.val)
IntegerModP.__name__ = 'IntegerMod%s' % p # rename created class
return IntegerModP
IntegerMod4 = IntegerModP(4)
i = IntegerMod4(3)
j = IntegerMod4(2)
print i + j # 1
print repr(i + j) # IntegerMod4(1)
Metaclasses are for when your class needs to behave differently from a normal class or when you want to alter the behavior of the class statement. Neither of those apply here, so there's really no need to use a metaclass. In fact, you could just have one ModularInteger class with instances that record their value and modulus, but assuming you don't want to do that, it's still easy to do this with an ordinary class statement:
def integers_mod_p(p):
class IntegerModP(object):
def __init__(self, n):
self.n = n % IntegerModP.p
def typecheck(self, other):
try:
if self.p != other.p:
raise TypeError
except AttributeError:
raise TypeError
def __add__(self, other):
self.typecheck(other)
return IntegerModP(self.n + other.n)
def __sub__(self, other):
...
IntegerModP.p = p
IntegerModP.__name__ = 'IntegerMod{}'.format(p)
return IntegerModP