all the examples shown just explain how to create a singleton of a class without the instantiation of any members.
But how can I produce a singleton of the following class in Python 3:
class NotOneOnly:
def __init__(self, a, b):
print("Instatiation of objects.")
self.a = a
self.b = b
def run(self):
print("Variable a = " + str(self.a) + " and variable b = " +
str(self.b))
In the main program, the use would be:
not_one_only = NotOneOnly(5, 10)
not_one_only.run()
Thanks 4 help.
After investigating a little bit, I've discovered this. So my conclusion is:
class OneOnly:
_singleton = None
a = None
b = None
def __new__(cls, a, b):
if not cls._singleton:
print("Object is created and the variables are instantiated.")
cls._singleton = super(OneOnly, cls).__new__(cls)
cls.a = a
cls.b = b
else:
print("Sorry, byt object is already made.")
return cls._singleton
def run(self):
print("Variable a = " + str(self.a) + " and variable b = " + str(self.b))
Now in the mainfile I made the following experiments showing that the singleton was created in the right way:
print("Singleton Experiment:")
a = 10
b = 5
one_only1 = OneOnly(a, b)
print(one_only1)
one_only1.run()
one_only2 = OneOnly(1, 2)
print(one_only2)
one_only2.run()
one_only1.a = 100
one_only1.run()
one_only2.run()
Now the output is:
Singleton Experiment:
Object is created and the variables are instantiated.
<__main__.OneOnly object at 0x7fa4295cbcc0>
Variable a = 10 and variable b = 5
Sorry, byt object is already made.
<__main__.OneOnly object at 0x7fa4295cbcc0>
Variable a = 10 and variable b = 5
Variable a = 100 and variable b = 5
Variable a = 100 and variable b = 5
I have been implementing function overloading using function to find the area of various figures(that includes square,circle and rectangle) but when I try to implement the concept here is the error that I get.
I made an instance of the class and then tried to call all the function with difference in the number of parameters. But still I am getting a lot of error.
from abc import abstractmethod
class Poly:
def __init__(self,n=0):
self._n = n
def area(self,a):
if isinstance(r,int):
return a ** 2
def area(self,b,pi):
if isinstance(a,float):
ar = pi * b * b
return ar
def area(self,l,r,ar):
if isinstance(l,int) and isinstance(r,int):
ar = l * r
return l*r
if __name__ == '__main__':
p = Poly()
pi = 3.14
ar = 0
l = 3
r = 4
b = 10
a = 2
peroi1 = p.area(a)
print(peroi1)
peroi2 = p.area(b,pi)
print(peroi2)
peroi3 = p.area(l,r,ar)
print(peroi3)
The expected output should give the area of square,circle and rectangle respectively but I get the following error.
Traceback (most recent call last):
File "overloadpractice.py", line 28, in <module>
peroi1 = p.area(a)
TypeError: area() missing 2 required positional arguments: 'r' and 'ar'
You can do something like this, but there are better ways. I'll come up with a better example in a little while:
class Poly:
def __init__(self, n=0):
self._n = n
def area(self, *args):
if len(args) == 1:
if isinstance(a, int):
return r ** 2
elif len(args) == 2:
if isinstance(a, float):
return pi * b * b
elif len(args) == 3:
if isinstance(l, int) and isinstance(r, int):
ar = l * r
return l*r
else:
return 'invalid number of arguments'
if __name__ == '__main__':
pi = 3.14
ar = 0
l = 3
r = 4
b = 10
a = 2
p = Poly()
peroi1 = p.area(a)
print(peroi1)
peroi2 = p.area(b, pi)
print(peroi2)
peroi3 = p.area(l, r, ar)
print(peroi3)
A better(easier to test and maintain) example:
from math import pi
SQUARE = 1
CIRCLE = 2
RECTANGLE = 3
get_area = {
SQUARE: lambda side : side * side,
CIRCLE: lambda radius, _ : pi * radius * radius,
RECTANGLE: lambda length, width, _ : length * width
}
class Poly:
def __init__(self, n=0):
self._n = n
def area(self, *args):
return get_area.get(len(args), lambda: 'invalid number of arguments')(*args)
if __name__ == '__main__':
ar = 0
l = 3
r = 4
b = 10
a = 2
# moved pi to an import
square = Poly()
circle = Poly()
rectangle = Poly()
print(square.area(a)) # 4
print(circle.area(b, pi)) # 14.1592653589793
print(rectangle.area(l, r, ar)) # 12
print(square.area()) # invalid number of variables
I was playing with the recursive Ackermanns function. For certain values my prompt whould not show every calculated output 'cause Python whould exceed its recursive limit so fast that whould freeze the prompt before the "easy" parts whould catch up with it.
So I thought I could add a recursive counter and a quick pause after a full execution of the function. I was getting the anticipated outputs until it reached the values (1,0). After that I got a TypeError: can only concatenate tuple (not "int") to tuple.
My code is as follows:
import time
import sys
sys.setrecursionlimit(3000)
def ackermann(i,j,rec):
output = None
if i==0:
output = j+1
elif j==0:
output = ackermann(i-1,1,rec)
rec=rec+1
else:
output = ackermann(i-1,ackermann(i,j-1,rec),rec)
rec=rec+1
return output,rec
rec=0
for i in range(5):
for j in range(5):
print("(",i,",",j,")= ",ackermann(i,j,rec))
time.sleep(2)
Notice that removing all instances of rec (my recurence counter), the program runs fine. (You can see all outputs for values i,j = 3)
Can someone point out how to correct my code or propose a different method of finding how many times the Ackermann function has calls itself ?
Also, I've noticed that putting a limit of 5000 whould crash my python kernel very fast. Is there an upper limit ?
I use the latest Anaconda.
EDIT
I tried to implement the same function using a list as a parameter with the following data [i,j,output,#recursion]
import time
import sys
sys.setrecursionlimit(3000)
def ackermann(*rec):
rec=list(rec)
print(rec) # see the data as they initialize the function
if rec[0][0]==0:
rec[0][1]=rec[0][1]+1
rec[0][2] = rec[0][1]+1
elif rec[0][1]==0:
rec[0][0]=rec[0][0]-1
rec[0][1]=1
rec = ackermann()
rec[0][3]=rec[0][3]+1
else:
rec[0][0]=rec[0][0]-1
rec[0][1] = ackermann()
rec = ackermann()
rec[0][3]=rec[0][3]+1
return rec
for i in range(5):
for j in range(5):
rec=[i,j,0,0]
print(ackermann(rec))
time.sleep(1)
But this time I get a IndexError: list index out of rangebecause for some unknown reason my list gets emptied
OUTPUT:
[[0, 0, 0, 0]]
[[0, 1, 2, 0]]
[[0, 1, 0, 0]]
[[0, 2, 3, 0]]
[[0, 2, 0, 0]]
[[0, 3, 4, 0]]
[[0, 3, 0, 0]]
[[0, 4, 5, 0]]
[[0, 4, 0, 0]]
[[0, 5, 6, 0]]
[[1, 0, 0, 0]]
[]
The problem with the original implementation is that
return output, rec
will happily create a tuple when output and rec are both numbers, which is true whenever i=0. But once you get to i=1, j=0 the function calls Ackerman on (0,1,rec), which returns a tuple, to which it then cannot add the integer rec, hence the error message. I believe I have worked with that idea, though, almost unchanged, except rather than trying to pass and return rec, I made it global (ugly, I know). I also reformatted the output so I could read it better. Thus:
import time
import sys
sys.setrecursionlimit(3000)
def ackermann(i,j):
global rec
output = None
if i==0:
output = j+1
elif j==0:
output = ackermann(i-1,1)
rec=rec+1
else:
output = ackermann(i-1,ackermann(i,j-1))
rec=rec+1
return output
for i in range(5):
for j in range(5):
rec = 0
print
print("ack("+str(i)+","+str(j)+") = "+str(ackermann(i,j)))
print("rec = "+str(rec))
print
time.sleep(1)
and the output, before erroring out, is,
ack(0,0) = 1
rec = 0
ack(0,1) = 2
rec = 0
ack(0,2) = 3
rec = 0
ack(0,3) = 4
rec = 0
ack(0,4) = 5
rec = 0
ack(1,0) = 2
rec = 1
ack(1,1) = 3
rec = 2
ack(1,2) = 4
rec = 3
ack(1,3) = 5
rec = 4
ack(1,4) = 6
rec = 5
ack(2,0) = 3
rec = 3
ack(2,1) = 5
rec = 8
ack(2,2) = 7
rec = 15
ack(2,3) = 9
rec = 24
ack(2,4) = 11
rec = 35
ack(3,0) = 5
rec = 9
ack(3,1) = 13
rec = 58
ack(3,2) = 29
rec = 283
ack(3,3) = 61
rec = 1244
ack(3,4) = 125
rec = 5213
ack(4,0) = 13
rec = 59
It seems to me there are only one or two other values (it will choke on 4,2 I believe, no matter what, so you would need to get 5, 0 first) you could hope to get out this way, no matter how much you tinker.
I am a little troubled that rec appears to exceed the recursion limit, but I think Python must be interpreting along the way somehow, so that it gets deeper than one might think, or that I don't fully understand sys.recursionlimit (I looked at rec a few times, and at the very least I followed your lead on calculating it; also, as a sanity check I switched the order of incrementing it and the function call and got the same results).
EDIT: I added another parameter to track how deeply any particular call ever recurses. That turns out to be typically less than (and at most one more than) "rec." rec represents (actually 1 less than) how many times the function is called to make the particular calculation, but not all of these need be on the Python interpreter stack simultaneously.
Revised code:
import time
import sys
sys.setrecursionlimit(3000)
def ackermann(i,j,d):
global rec
global maxDepth
if ( d > maxDepth ) : maxDepth = d
output = None
if i==0:
output = j+1
elif j==0:
rec=rec+1
output = ackermann(i-1,1, d+1)
else:
rec=rec+1
output = ackermann(i-1,ackermann(i,j-1, d+1),d+1)
return output
for i in range(5):
for j in range(5):
rec = 0
maxDepth=0
print
print("ack("+str(i)+","+str(j)+") = "+str(ackermann(i,j,1)))
print("rec = "+str(rec))
print("maxDepth = "+str(maxDepth))
print
time.sleep(1)
revised output (before it gives up)
ack(0,0) = 1
rec = 0
maxDepth = 1
ack(0,1) = 2
rec = 0
maxDepth = 1
ack(0,2) = 3
rec = 0
maxDepth = 1
ack(0,3) = 4
rec = 0
maxDepth = 1
ack(0,4) = 5
rec = 0
maxDepth = 1
ack(1,0) = 2
rec = 1
maxDepth = 2
ack(1,1) = 3
rec = 2
maxDepth = 3
ack(1,2) = 4
rec = 3
maxDepth = 4
ack(1,3) = 5
rec = 4
maxDepth = 5
ack(1,4) = 6
rec = 5
maxDepth = 6
ack(2,0) = 3
rec = 3
maxDepth = 4
ack(2,1) = 5
rec = 8
maxDepth = 6
ack(2,2) = 7
rec = 15
maxDepth = 8
ack(2,3) = 9
rec = 24
maxDepth = 10
ack(2,4) = 11
rec = 35
maxDepth = 12
ack(3,0) = 5
rec = 9
maxDepth = 7
ack(3,1) = 13
rec = 58
maxDepth = 15
ack(3,2) = 29
rec = 283
maxDepth = 31
ack(3,3) = 61
rec = 1244
maxDepth = 63
ack(3,4) = 125
rec = 5213
maxDepth = 127
ack(4,0) = 13
rec = 59
maxDepth = 16
In your edited version of the code, you used a *arg in your def for ackerman and made it explicitly a list, and you get eleven output lists containing a four-element list in each until on the twelfth recursion you get an empty list. So, did the first eleven lists contain the expected elements according to the ackermann constraints? Also, on the twelfth recursion, you say the list was "emptied." I wonder for analytical purposes if it might make sense to say instead it wasn't filled in the first place. That is, not that something emptied it but that something didn't fill it as expected on the twelfth time through.