Maximum recursion depth exceeded while comparing two objects - python

I am currently new to Python and I'm not sure why i'm getting the error:
a<r raised exception RuntimeError: maximum recursion depth exceeded while calling a Python object
when I do this:
a = Rational(1,3)
r = Rational(0,5)
print(a<r)
My current code is:
class Rational:
def _gcd(x,y):
while y != 0:
x, y = y, x % y
return x
def __init__(self, num = 0, denom = 1):
gcd = Rational._gcd(num, denom)
self.num = int(num / gcd)
self.denom = int(denom / gcd)
def __lt__(self, right):
return Rational(self.num, self.denom) < Rational(right.num, right.denom)
It also happens for all the other relational operators when I do the same thing.
Can someone enlighten me on this particular matter? How do I approach or fix this?
Thanks!

This line:
Rational(self.num, self.denom) < Rational(right.num, right.denom)
… is calling the __lt__ method again, leading to an infinite recursion. Try a different approach, assuming that we're using Python 3.x (or in Python 2.x, that from __future__ import division was executed beforehand), this should work:
self.num/self.denom < right.num/right.denom

Related

How can I ensure that a function is "defined" in Python?

Trying to learn python as a java programmer. I would really appreciate some insight into why my program is telling me that my "isPrime" function isn't defined, especially with the use of 'self.'
import math
class Problem10:
def sumOfPrimesX(self, number):
sum = 0
for i in range(0, number):
if isPrime(i):
sum += i
return sum
def isPrime(self, x):
for n in range(0, math.floor(x/2)):
if x % n == 0:
return False
return True
print(sumOfPrimesX(input()))
all functions need it as their first parameter in a python program
No, only the instance methods, the methods related to a specific instance of a class. A simple function can need to parameter.
And you won't see the parameter self filled with the classic way of calling it, if you call the method on a instance it'll be filled by it
p = Problem10()
p.sumOfPrimesX(int(input("Give a value"))) # call on instance, one paramater given
# same as
Problem10.sumOfPrimesX(Problem10(), int(input("Give a value")))
# call on class itself, need to pass an instance as first to fill 'self
Also you need to wrap the input in an int, also start the loop at 2
p = Problem10()
print(p.sumOfPrimesX(int(input("Give a value"))))
class Problem10:
def isPrime(self, x):
for n in range(2, math.floor(x / 2)):
if x % n == 0:
return False
return True
The issue is both isPrime and sumofPrimesX are methods of the class Problem10.
Try the following:
import math
class Problem10:
def sumOfPrimesX(self, number):
sum = 0
for i in range(0, number):
if self.isPrime(i):
sum += i
return sum
def isPrime(self, x):
for n in range(0, math.floor(x/2)):
if x % n == 0:
return False
return True
pv = Problem10()
print(pv.sumOfPrimesX(input()))

Python - RecursionError is inconsistently thrown

Why does Python throw a RecursionError on line 10 but not on line 13?
def fib(n, a = [0,1]):
if len(a) > n:
return a[n]
a.append(fib(n - 1, a) + fib(n - 2, a))
return a[n]
def main():
x = 998
print(fib(x)) # RecursionError
for i in range(1000):
print(fib(i)) # No Error
main()
Looking further into this, it looks like the previously mentioned mutable default argument treatment by python is actually the reason behind this. Instead of creating a new list every time the function is called, the list is created once when the function is defined.
Here is a function exploiting this feature, so that calling fib(998) doesn't throw the RecursionError:
def fib(n, a = [0,1]):
if len(a) > n:
return a[n]
while len(a) <= n:
a.append(fib(len(a) - 1) + fib(len(a) - 2))
return a[n]

Guidance needed with 'class' task (beginner)

It looks daunting, but please bear with me, it's not as difficult as it looks. I have a code here about beam deflection. It's just some maths and numbers at this point. Only the last part requires attention.
class beam(object):
"""This class is models the deflection of a simply supported beam under
multiple point loads, following Euler-Bernoulli theory and the principle of
superposition.
"""
def __init__(self, E, I, L):
"""The class costructor.
"""
self.E = 8.0E9 # Young's modulus of the beam in N/m^2
self.I = 1.333E-4 # Second moment of area of the beam in m^4
self.L = 5.0 # Length of the beam in m
self.Loads = [(0.0, 0.0)] # the list of loads applied to the beam
self.name = "beam"
def setLoads(self, Loads):
'''This function allows multiple point loads to be applied to the beam
using a list of tuples of the form (load, position)
'''
self.Loads = Loads
The "def __ init __" and "def setLoads" were given, so the above doesn't need changing. I inputted values for self.E, I and L since I thought I needed them there, but those numbers can be replaced back to the letters that they were before.
def beamDeflection(self, Load, x):
"""Just a simple calculation, really.
"""
E = 8.09 * (10 ** 9)
I = 1.333 * (10 ** -4)
L = 5
a = 2.5
b = a + (x - a)
(P1, a) = Load
if 0 <= x <= 2.5:
beamDeflection = ((P1*b*x)/(6*L*E*I))*((L**2)-(x**2)-(b**2))
else:
if 2.5 < x <= 5:
beamDeflection = ((P1*b)/(6*L*E*I)) / (((L/b)*((x-a)**3)) -
(x**3) + (x*((L**2) -
(b**2))))
return beamDeflection
The above "beamDeflection" is the simple code I typed up that just calculates deflection in a beam using a formula that's already been given. Essentially, if a weight is put on the left side of the beam, it'll calculate a number out and the same for the other side.
def getTotalDeflection(self, x):
"""The function getTotalDeflection(self, x) should go through each load tuple in the
list.Loads and calculate the beam deflection at point x (Hint: the function you just
created could be handy here!). getTotalDeflection should return the total deflection at x,
which is the sum over each of the individual deflections.
"""
My understanding is that I need to a "for" loop to go through each load tuple while involving the self.load. I'm not sure on how to go about combining both of those things together. If anyone can help me out, I'd really, really appreciate it.
What you are looking for is probably this (else please clarify):
def getTotalDeflection(self, x):
return sum(self.beamDeflection(loadval, x) for loadval in self.Loads)
I think this is what you want:
def getTotalDeflection(self, x):
total = 0
# For every load in `Loads`
for load in self.Loads:
# Compute the deflection and add it to the total
total += self.beamDeflection(load, x):
return total

why is there this TypeError?

i am trying to find the square root a number through the function sqrt(a). fixedPoint(f, epsilon) is a helper function. the problem is that i get a this TypeError: 'float' object is not callable. i am new to programming, so if anybody can help and find were is the bug and explain what does this error mean ??
def fixedPoint(f, epsilon):
"""
f: a function of one argument that returns a float
epsilon: a small float
returns the best guess when that guess is less than epsilon
away from f(guess) or after 100 trials, whichever comes first.
"""
guess = 1.0
for i in range(100):
if abs(f(guess) - guess) < epsilon:
return guess
else:
guess = f(guess)
return guess
def sqrt(a):
def tryit(x):
return 0.5 * (a/x + x)
return fixedPoint(tryit(a), 0.0001)
In sqrt function, the code is passing the return value of the tryit (which is a float value), not tryit itself.
Passing the function itself will solve the problem.
def sqrt(a):
def tryit(x):
return 0.5 * (a/x + x)
return fixedPoint(tryit, 0.0001)

Arithmetic Progression in Python without storing all the values

I'm trying to represent an array of evenly spaced floats, an arithmetic progression, starting at a0 and with elements a0, a0 + a1, a0 + 2a1, a0 + 3a1, ...
This is what numpy's arange() method does, but it seems to allocate memory for the whole array object and I'd like to do it using an iterator class which just stores a0, a1 and n (the total number of elements, which might be large).
Does anything that does this already exist in the standard Python packages?
I couldn't find it so, ploughed ahead with:
class mylist():
def __init__(self, n, a0, a1):
self._n = n
self._a0 = a0
self._a1 = a1
def __getitem__(self, i):
if i < 0 or i >= self._n:
raise IndexError
return self._a0 + i * self._a1
def __iter__(self):
self._i = 0
return self
def next(self):
if self._i >= self._n:
raise StopIteration
value = self.__getitem__(self._i)
self._i += 1
return value
Is this a sensible approach or am I revinventing the wheel?
Well, one thing that you are doing wrong is that it should be for i, x in enumerate(a): print i, x.
Also, I'd probably use a generator method instead of the hassle with the __iter__ and next() methods, especially because your solution wouldn't allow you to iterate over the same mylist twice at the same time with two different iterators (as self._i is local to the class).
This is probably a better solution which gives you random access as well as an efficient iterator. The support for the in and len operators are thrown in as a bonus :)
class mylist(object):
def __init__(self, n, a0, a1, eps=1e-8):
self._n = n
self._a0 = a0
self._a1 = a1
self._eps = eps
def __contains__(self, x):
y = float(x - self._a0) / self._a1
return 0 <= int(y) < self._n and abs(y - int(y)) < self._eps
def __getitem__(self, i):
if 0 <= i < self._n:
return self._a0 + i * self._a1
raise IndexError
def __iter__(self):
current = self._a0
for i in xrange(self._n):
yield current
current += self._a1
def __len__(self):
return self._n
Other answers answer the immediate problem. Note that if all you want is an iterator and you don't need random access, there's no need to write a whole iterator class.
def mylist(n, a0, a1):
for i in xrange(n):
yield a0 + i*a1
Only for reasons that are probably obvious to someone out there, iterating over mylist: for i,x in enumerate(a): print i,a doesn't return the values I expect but just a whole lot of references to the mylist instance. What am I doing wrong?
The culprit is print i,a. You are printing a, which is an array. You ought to print x instead. Chane this line to:
print i,x
Also a couple of things:
Change you class name to TitleCase. For e.g. class MyList or class Mylist.
It is a good idea to inherit from object if you are using Python 2.x. So class MyList(object): ...
You're enumerating over a, so printing it will print a lot of references to it. Print x instead.
Yes, there's a built-in generator for this (Python 2.7 and up):
import itertools
mygen = itertools.count(a0,a1)
If you don't have Python 2.7 yet (Python 2.4 and up):
import itertools
mygen = (a0 + a1*i for i in itertools.count())

Categories