Function runs by itself but not when in a class - python

class Fibonacci:
def fn(num):
if num <= 0:
return 0
if num <= 1:
return 1
else:
Result = fn(num - 1) +fn(num - 2)
return Result
amount = int(input("How many numbers do you want? : "))
i = 1
while i < amount:
FibValue = fn(i)
print(FibValue)
i += 1
Fibonacci()
Here are my errors:
File "C:/Users/Carsten/PycharmProjects/untitled/Lesson13.py", line 30, in <module>
class Fibonacci:
File "C:/Users/Carsten/PycharmProjects/untitled/Lesson13.py", line 45, in Fibonacci
FibValue = fn(i)
File "C:/Users/Carsten/PycharmProjects/untitled/Lesson13.py", line 38, in fn
Result = fn(num - 1) +fn(num - 2)
NameError: name 'fn' is not defined
I'm not quite sure as to why I can run the def Fibonacci: function on its own but as soon as I put it under a class it gives me these errors. I'm still a beginner and have little idea of what these errors mean but even looking them up isn't of much assistance. Any help is appreciated. I realize I can use this as just a standalone function but I'm in the middle of a problem in the youtube series I'm watching to teach myself and I don't want to simply skip ahead in the video and just see the answer to the rest of the problem. Thanks

When you change the function to a class method (i.e. put it inside the class), then only an object of that class can invoke the function. The syntax is as stanleyli mentioned. Perhaps a little more clear:
fib_obj = Fibonacci()
fib_value = fib_obj.fn(i)
As Ignazio already pointed out, this is a very poor example of Class usage. The class has no attributes (data associated with the object), and making the class only makes it harder to use the function.
A Class is better used when you have a collection of data and functions that act on that data, where the combination embodies a higher-level concept. For instance, a game board with piece locations and movement functions would be a good use of a class.
I understand now. Also see the tutorial references here. Essentially, an iterable is a Class that includes a next (explicit) and/or __next__ (implicit) method. That's why you start with the class structure.
Once you've done that, your main program reduces to
for i in Fibonacci(amount):
print i

Related

Controlling dynamic properties in Shady according to video frames not time

I am trying to use Shady to present a sequence of image frames. I'm controlling the flow from another machine, so that I first instruct the machine running Shady to present the first frame, and later on to run the rest of the frames.
I create a World instance, and attach to it an animation callback function. Within this callback I listen for communications from the other machine (using UDP).
First I receive a command to load a given sequence (stored as a numpy array), and I do
def loadSequence(self, fname):
yy = np.load(fname)
pages = []
sz = yy.shape[0]
for j in range(yy.shape[1]/yy.shape[0]):
pages.append(yy[:, j*sz:(j+1)*sz])
deltax, deltay = (self.screen_px[0] - sz) / 2, (self.screen_px[1] - sz) / 2
if (self.sequence is None):
self.sequence = self.wind.Stimulus(pages, 'sequence', multipage=True, anchor=Shady.LOCATION.UPPER_LEFT, position=[deltax, deltay], visible=False)
else:
self.sequence.LoadPages(pages, visible=False)
When I receive the command to show the first frame, I then do:
def showFirstFrame(self, pars):
self.sequence.page = 0 if (pars[0] == 0) else (len(self.sequence.pages) - 1)
self.sequence.visible = True
But what do I do now to get the other frames to be be displayed? In the examples I see, s.page is set as a function of time, but I need to show all frames, regardless of time. So I was thinking of doing something along these lines:
def showOtherFrames(self, pars, ackClient):
direction, ack = pars[0], pars[2]
self.sequence.page = range(1, len(self.sequence.pages)) if (direction == 0) else range(len(self.sequence.pages)-2, -1, -1)
But this won't work. Alternatively I thought of defining a function that takes t as argument, but ignores it and uses instead a counter kept in a global variable, but I'd like to understand what is the proper way of doing this.
When you make s.page a dynamic property, the function assigned to it must take one argument (t), but you can still just use any variables in the space when defining that function, and not even use the time argument at all.
So, for example, you could do something as simple as:
w = Shady.World(...)
s = w.Stimulus(...)
s.page = lambda t: w.framesCompleted
which will set the page property to the current frame count. That sounds like it could be useful for your problem.
Your global-variable idea is one perfectly valid way to do this. Or, since it looks like you're defining things as methods of an instance of your own custom class, you could use instance methods as your animation callbacks and/or dynamic property values—then, instead of truly global variables, it makes sense to use attributes of self:
import Shady
class Foo(object):
def __init__(self, stimSources):
self.wind = Shady.World()
self.stim = self.wind.Stimulus(stimSources, multipage=True)
self.stim.page = self.determinePage # dynamic property assignment
def determinePage(self, t):
# Your logic here.
# Ignore `t` if you think that's appropriate.
# Use `self.wind.framesCompleted` if it's helpful.
# And/or use custom attributes of `self` if that's
# helpful (or, similarly, global variables if you must).
# But since this is called once per frame (whenever the
# frame happens to be) it could be as simple as:
return self.stim.page + 1
# ...which is indefinitely sustainable since page lookup
# will wrap around to the number of available pages.
# Let's demo this idea:
foo = Foo(Shady.PackagePath('examples/media/alien1/*.png'))
Shady.AutoFinish(foo.wind)
Equivalent to that simple example, you could have the statement self.stim.page += 1 (and whatever other logic) inside a more-general animation callback.
Another useful tool for frame-by-frame animation is support for python's generator functions, i.e. functions that include a yield statement. Worked examples are included in python -m Shady demo precision and python -m Shady demo dithering.
It can also be done in a StateMachine which is always my preferred answer to such things:
import Shady
class Foo(object):
def __init__(self, stimSources):
self.wind = Shady.World()
self.stim = self.wind.Stimulus(stimSources, multipage=True)
foo = Foo(Shady.PackagePath('examples/media/alien1/*.png'))
sm = Shady.StateMachine()
#sm.AddState
class PresentTenFrames(sm.State):
def ongoing(self): # called on every frame while the state is active
foo.stim.page += 1
if foo.stim.page > 9:
self.ChangeState()
#sm.AddState
class SelfDestruct(sm.State):
onset = foo.wind.Close
foo.wind.SetAnimationCallback(sm)
Shady.AutoFinish(foo.wind)

Running unit tests on a non OOP code without any return value

I have a script of this form which is called in a program (from another similar function). I need to use unittest module to write tests for this function.
It doesn't exactly return anything but changes a lot of globals
It takes inputs
I can't change it to an OOP code right now
I want to test cases where I change a certain global varible and see if ,let's say, TOTFRAC is positive or something.
I have read tests for OOP codes where I call each variable as an object parameter, but what do I do if my code isn't Object Oriented.
Note: I have removed a lot of lines of code because it is rather long, so things might not exactl make sense
import numpy
import math
def SETUP(LAST):
def GOTO999():
print(' ERROR IN GAS INPUT : NGAS=',NGAS,'\n')
for J in range(1,6):
# print(J)
print(' N=',J,' NGAS=',NGASN[J],' FRAC=',FRAC[J])
LAST=1
return
# A lot of globals
# Initialising variables
NBREM=[]
EBRTOT=[]
for K in range(1,6):
NBREM.append(0)
EBRTOT.append(0.0)
NGAS=int(input('NGAS'))
NEVENT=int(input('NEVENT'))
IMIP=int(input('IMIP'))
NDVEC=int(input('NDVEC'))
NSEED=int(input('NSEED'))
ESTART=float(input('ESTART'))
ETHRM=float(input('ETHRM'))
ECUT=float(input('ECUT'))
ICOUNT=0
if(IMIP == 1):
ICOUNT=1
if(NGAS == 0):
LAST=1
return
if(ESTART > 3.0*(10**6) and IMIP == 3):
print(' SUBROUTINE STOPPED: X-RAY ENERGY=','%.3f' % ESTART,'EV. MAXIMUM ENERGY 3.0MEV')
sys.exit()
if(IMIP != 1 and NEVENT > 10000):
print(' SUBROUTINE STOPPED: NUMBER OF EVENTS =',NEVENT,' LARGER THAN ARRAY LIMIT OF 10000')
sys.exit()
NGASN=[]
for i in range(1,6):
NGASN.append(int(input('NGASN'+str(i))))
FRAC=[]
for i in range(1,6):
FRAC.append(round(float(input('FRAC')),4))
TEMPC=round(float(input('TEMPC')),4)
TORR=round(float(input('TORR')),4)
# more inputs
if(IWRITE != 0):
outputfile=open("DEGRAD.OUT","w")
EBIG=0.05*ESTART/1000.
EFINAL=ESTART*1.0001+760.0*EBIG/TORR*(TEMPC+ABZERO)/293.15*EFIELD
if(EFINAL < (1.01*ESTART)):
EFINAL=1.01*ESTART
# CHECK INPUT
TOTFRAC=0.00
if(NGAS == 0 or NGAS > 6):
GOTO999()
for J in range(1,NGAS):
print('J',J)
if(NGASN[J]== 0 or FRAC[J] == 0.00):
GOTO999()
TOTFRAC=TOTFRAC+FRAC[J]
if(abs(TOTFRAC-100.00)> 1*(10**-6)):
print(TOTFRAC)
GOTO999()
if(NDVEC): #22594
PHI=0
THETA=0
elif(NDVEC==-1):
PHI=0
THETA=numpy.arccos(-1)
elif(NDVEC==0):
PHI=0.0
THETA=API/2.0
elif(NDVEC==2):
R3=DRAND48(0.0,1.0)
PHI=TWOPI*R3
R4=DRAND48(1.5, 1.9)
THETA=numpy.arccos(1.0-2.0*R4)
else :
print('DIRECTION OF BEAM NOT DEFINED NDVEC =',NDVEC)
sys.exit()
if(NSEED != 0):
RM48(NSEED,0,0)
CORR=ABZERO*TORR/(ATMOS*(ABZERO+TEMPC)*100.00)
GOTO999()
# end
As #hoefling has pointed out, the code as it is now is hardly testable. But, this is not because it is not object oriented. You can easily test non-object oriented code as long as it has a suitable structure. Which means, break long functions down into smaller ones, use function arguments and return values rather than global variables etc. - none of this has anything to do with OOP. In fact, your code violates many coding principles that were known and formulated long before OOP was en vogue (1974), see https://en.wikipedia.org/wiki/The_Elements_of_Programming_Style.
I recommend reading one or some of the following books:
Code Complete by Steve McConnell - a classic book about how to write great code.
Refactoring by Martin Fowler - how to migrate from not-so-great code to better code.
Clean Code by Robert C. Martin - again, how to write great code.

Wrapper Function in Python

#***This code uses wrapper function to print the phone number in a
standard format with country code (if not supplied in the input)***
def ori_func(a):
mm=[]
def wraap(*args):
for k in args:
for i in k:
#print(i)
if len(str(i))==10:
mm.append("+91"+str(i))
elif str(i)[0]=="0" and len(str(i))==11:
mm.append("+91"+str(i)[1:])
#elif len(str(i))==12 and i[0]=="+":
# mm.append(i)
elif len(str(i)) == 12:
mm.append("+"+str(i))
#print (mm)
return a(mm)
return wraap
#ori_func
def srt_phone(mm):
#sorted(int(mm))
for j in sorted(mm):
cc=str(j)[:3]
mmn1=str(j)[3:8]
mmn2=str(j)[8:]
print (cc+" "+mmn1+" "+mmn2)
m=[1234567891, 912345678923, +919876543219,"07418529637"]
srt_phone(m)
This code works fine as per my knowledge. However I need you to look-through my code and let me know my level of Wrapper function knowledge is correct
When I pass a list to wrapper function, do I need to really use 2 "For" loops in wrapper function like I did? Is there any other way?
When we asked to get the phone number as input in INT format,how to handle with the input that starts with 0?
Thanks
Yes. There are other ways but that way is pretty clean.
You can't, and I suggest not treating phone numbers as numbers because they aren't real numbers. Real numbers can't start with a + or a 0.
Your code looks fine to me; I'd have done a few things differently but that's just personal preference. I do recommend that you look into using #functools.wraps(a) on your inner function.

Python TypeError: 'function' object is not subscriptable in nested function when i try to implement switch case

I am trying to code a random decision between 3 machines.
Since Python does not have any switch/case function, I resorted to if and elif.
Each machine (line1(),line2(),line3()) has its own function as well.
However, I have been getting errors.
Please advise me on what is going wrong.
machine_choice = [1,2,3]
selected_machine = random.choice(machine_choice)
print(selected_machine)
def machines(selected_machine):
if selected_machine == 1:
print("machine 1 randomly selected")
line1()
elif selected_machine == 2:
print("machine 2 randomly selected")
line2()
else:
print("machine 3 randomly selected")
line3()
machines(selected_machine)
def line1():
if machine1["hardness"] < rev[i][1]["condition"]:
print("\tMachine 1 hardness breached, will take 30mins for changing the system")
machine1["hardness"] = 10
time = line1
machine1["schedule"].append([d,"machine 1",time,"change",30.,time.add(minutes=30)])
print("\tno activities from {} to {}".format(time,time.add(minutes=30)))
time = time.add(minutes=30)
print("\tdone changing at time: ",time)
print("\tcurrent log: ",machine1["schedule"],"\n")
d+=1
line1=time
#line1 = max(time,line1,line2)
machine1["schedule"].append([d,"machine 1",line1,"feeding",5.,line1.add(minutes=5)])
line1 = line1.add(minutes=5)
d+=1
machine1["schedule"].append([d,"machine 1",line1,rev[i][0],rev[i][1]["duration"],line1.add(minutes=rev[i][1]["duration"])])
line1 = line1.add(minutes=rev[i][1]["duration"])
time = time.add(minutes=5)
d+=1
if rev[i][1]["quantity"] == 0:
i += 1
I am trying to code a random decision between 3 machines.
In Python, functions are nothing special, you can use them just like any other object.
def machine_one():
return 'Machine One'
def machine_two():
return 'Machine Two'
def machine_three():
return 'Machine Three'
machines = [machine_one, machine_two, machine_three]
print(random.choice(machines)())
The message means that you try to access to some python object defined as a function as if it were an array. The most likely candidate looking as the code you provided is machine_choice.
But please provide a working minimal example, which in that case means including import of necessary modules (random) and lines function.
Regarding the purpose of the code (faking a switch) the cascaded if solution is usually not a very good solution. Using random.choice with an array or a dictionnary or an array with random number as key or index would be much more pythonic.
Also using switch is a common code smell in OO programming and is often best replaced using object polymorphism and a factory.
You may have a look at python switch replacement for details.

Python using mock for a multiple user inputs

A follow on for this question.
I am accepting user input in a for loop and have written a test case, test_apple_record. In this for loop, it queries a method self.dispatch_requested() ( not shown) which can randomly return True or False. Based on this answer, the code asks user for another input -- where the tray should be dispatched.
I am using the side_effect argument for mock.patch. How to automatically pass the hotel number as the user input using mock? I still want to continue passing the numbers [5, 6, 7] to the for loop, but now also want to pass in the hotel number based on response by self.dispatch_requested()
thank you
class SomeClass(unittest.TestCase):
def apple_counter(self):
apple_record = {}
for i in range(3):
apple_tray = input("enter tray number:")
apple_record[apple_tray] = (i+1)*10
print("i=%d, apple_record=%s"%(i, apple_record))
if self.dispath_requested():
number = input("Enter Hotel number to dispatch this tray:")
update_hotel_record(number, apple_tray)
def update_hotel_record(self, number, tray):
self.hotel_record[number] = tray
def test_apple_record(self):
with mock.patch('builtins.input', side_effect=[5, 6, 7]):
self.apple_counter()
You actually want your side_effect to look like this:
m_input.side_effect = [1, 100, 2, 200, 3, 300]
Each time the input method is called, it will return the next item. So each time in your loop, you call input twice.
Also, I don't know the final structure of your unit test, however, seeing that you have a conditional statement around the second input that is called in your loop, you should probably set a mock around that method to always return True.
When you get to the scenario where you want to test your code for when self.dispath_requested() returns false, you have to keep in mind the second input will not be called, so your side_effect has to be re-written accordingly to match the expected behaviour for your code.
Also, finally, again, I'm not sure what your code actually looks like, however, based on how you seem to have your actual implementation and test code under the same class, I strongly advise not doing that. Try a structure similar to this:
Create a separate test class:
class Tests(unittest.TestCase):
def setUp(self):
self.s = SomeClass()
#patch('__builtin__.input')
def test_apple_record(self, m_input):
m_input.side_effect = [1, 100, 2, 200, 3, 300]
self.s.apple_counter()
if __name__ == '__main__':
unittest.main()
So, you create an instance of SomeClass, and then this in effect will let you mock out the properties of the object much easier, which will make your unit tests much easier to write.
You will also notice that I used a decorator (#patch) instead of the "with" context. It's a personal preference, and I find it much easier to read the code using decorators.
Hope this helps.
Turns out my last answer was not useless after all! As there is no way of knowing which input you require but to read the prompt, you could simply replace the input() function with one that gives different answers depending on the prompt.
# first we need a generator for each type of response to `input()`
def tray_number_generator():
trays = ["1", "5", "7"]
for i in trays:
yield i
trays = tray_number_generator()
def room_number_generator():
rooms = ["112", "543", "724"]
for i in rooms:
yield i
rooms = room_number_generator()
# this can be written simpler as a generator expression like this:
trays = (tray for tray in ["1", "5", "7"])
rooms = (room for room in ["112", "543", "724"])
# now you can write a function that selects the next output depending on the prompt:
def mock_input(prompt):
if "room" in prompt.lower():
return next(rooms)
if "tray" in prompt.lower():
return next(trays)
# this can now be used to replace the `input()` function
with mock.patch('builtins.input', mock_input):
do_stuff()
I don't want go deeply in how mock both input and dispatch_requested and couple the answers to have a complete control and write a good unit test for this method. I think it is more interesting how to change your design to make the test (and so the code) simpler and more clear:
class SomeClass(object):
def apple_counter(self):
apple_record = {}
for i in range(3):
apple_tray = input("enter tray number:")
apple_record[apple_tray] = (i+1)*10
print("i=%d, apple_record=%s"%(i, apple_record))
self._dispatch_and_ask_number()
def _dispatch_and_ask_number(self):
if self.dispatch_requested():
number = self._ask_hotel_number()
update_hotel_record(number, apple_tray)
def _ask_try_number(self):
return input("enter tray number:")
def _ask_hotel_number(self):
return input("Enter Hotel number to dispatch this tray:")
def update_hotel_record(self, number, tray):
self.hotel_record[number] = tray
Now you are in a better position to create a new class with just one responsibility of ask user input and then mock it to have a complete control in your test:
class AskUserInput(class):
try_number_message = "Enter tray number:"
hotel_number_message = "Enter Hotel number to dispatch this tray:"
def try_number(self):
return input(self.try_number_message)
def hotel_number(self):
return input(self.hotel_number_message)
And SomeClass can be changed like:
class SomeClass(object):
_ask = AskUserInput()
def apple_counter(self):
apple_record = {}
for i in range(3):
apple_tray = self._ask.try_number()
apple_record[apple_tray] = (i+1)*10
print("i=%d, apple_record=%s"%(i, apple_record))
self._dispatch_and_ask_number()
def _dispatch_and_ask_number(self):
if self.dispatch_requested():
number = self._ask.hotel_number()
update_hotel_record(number, apple_tray)
def update_hotel_record(self, number, tray):
self.hotel_record[number] = tray
And finally the test
class TestSomeClass(unittest.TestCase):
#patch("AskUserInput.try_number")
#patch("AskUserInput.hotel_number")
def test_apple_record(self, mock_try_number, mock_hotel_number):
# Now you can use both side_effects and return_value
# to make your test clear and simple on what you test.
If you are playing with legacy code this approch is not really useful, but if you are testing something that you are developing now is better to turn it in a more testable code: make your code more testable improve design almost every times.

Categories