I am having difficulty returning a specific function from a dictionary of predefined functions. Here is my code:
import random
def bos1():
print ("function 1")
def bos2():
print ("function 2")
def bos3():
print("function 3")
def bos4():
print("function 4")
count = 0
while True :
if count <4:
bos = "bos"
poz = random.randint(3, 4)
bos = bos+str(poz)
bosdict = {'bos1': bos1(),'bos2':bos2(),'bos3':bos3(),'bos4':bos4()}
count += 1
print("please only printe one",bosdict[bos])
print("count:\n", count)
input("")
else:
bos = "bos"
poz = random.randint(1, 2)
bos = bos+str(poz)
bosdict = {'bos1': bos1(),'bos2':bos2(),'bos3':bos3(),'bos4':bos4()}
count += 1
print("please only printe one",bosdict['bos'])
print("count:\n", count)
input("")
I have created a successful version of this program that uses arithmetic functions. It will return the appropriate function relative to the string that has been concatenated upon each iteration. However with functions that are meant to return a string it returns all four functions in the dictionary on each iteration. Why is this happening and how can I make it behave the same as the arithmetic dictionary?
you're not creating a dictionary of function but a dictionary of function calls (which are None since your functions return nothing): all functions are executed when creating the dictionary.
Remove the () in your dict, you'll use it after retrieving the value in the dict to call the function:
bosdict = {'bos1': bos1,'bos2':bos2,'bos3':bos3,'bos4':bos4}
Call a random function like this:
bosdict[random.choice(list(bosdict.keys()))]()
or maybe simpler you don't need the keys in that case, only the values:
random.choice(list(bosdict.values()))()
or with the generated name from random index:
bosdict["bos{}".format(count)]()
note that dynamically calling the functions only has some interest if the functions are slow to compute or have a side-effect or parameters, else it's better to create a static dictionary (using return instead of print as Chris noted).
Related
I wrote the code which does the first part of task: it returns the count of calls of function
def counter():
val = [0]
def generate_count():
val[0] += 1
return val[0]
return generate_count
generate_count = counter()
print(generate_count())
But also I must be able to send start value of count into the func. As I know if u enter in ur function that u need to pass arguments then u are not be able to leave value blank. For example: If u write like this
def func1(n):
then you must pass one argument to make it work otherwise it wont work, so how to make it possible to work if u pass any arguments else if u don`t?
Use a default value:
def func1(n=0):
<code>
This function can be called with a parameter n, or it can be called without n. If you call the function like this:
func1()
The value of the parameter n will be set to 0, as you didn't specify a value.
It would probably make more sense to use a builtin generator for this case.
def counter(n=0):
while True:
n += 1
yield n
generate_count = counter(1)
print(next(generate_count)) # > 2
How can I define a function in python in such a way that it takes the previous value of my iteration where I define the initial value.
My function is defined as following:
def Deulab(c, yh1, a, b):
Deulab = c- (EULab(c, yh1, a, b)-1)*0.3
return (Deulab,yh1, a,b)
Output is
Deulab(1.01, 1, 4, 2)
0.9964391705626454
Now I want to iterate keeping yh1, a ,b fixed and start with c0=1 and iterate recursively for c.
The most pythonic way of doing this is to define an interating generator:
def iterates(f,x):
while True:
yield x
x = f(x)
#test:
def f(x):
return 3.2*x*(1-x)
orbit = iterates(f,0.1)
for _ in range(10):
print(next(orbit))
Output:
0.1
0.2880000000000001
0.6561792000000002
0.7219457839595519
0.6423682207442558
0.7351401271107676
0.6230691859914625
0.7515327214700762
0.5975401280955426
0.7695549549155365
You can use the generator until some stop criterion is met. For example, in fixed-point iteration you might iterate until two successive iterates are within some tolerance of each other. The generator itself will go on forever, so when you use it you need to make sure that your code doesn't go into an infinite loop (e.g. don't simply assume convergence).
It sound like you are after recursion.
Here is a basic example
def f(x):
x += 1
if x < 10:
x = f(x)
return x
print (f(4))
In this example a function calls itself until a criteria is met.
CodeCupboard has supplied an example which should fit your needs.
This is a bit of a more persistent version of that, which would allow you to go back to where you were with multiple separate function calls
class classA:
#Declare initial values for class variables here
fooResult = 0 #Say, taking 0 as an initial value, not unreasonable!
def myFoo1(x):
y = 2*x + fooResult #A simple example function
classA.fooResult = y #This line is updating that class variable, so next time you come in, you'll be using it as part of calc'ing y
return y #and this will return the calculation back up to wherever you called it from
#Example call
rtn = classA.myFoo1(5)
#rtn1 will be 10, as this is the first call to the function, so the class variable had initial state of 0
#Example call2
rtn2 = classA.myFoo1(3)
#rtn2 will be 16, as the class variable had a state of 10 when you called classA.myFoo1()
So if you were working with a dataset where you didn't know what the second call would be (i.e. the 3 in call2 above was unknown), then you can revisit the function without having to worry about handling the data retention in your top level code. Useful for a niche case.
Of course, you could use it as per:
list1 = [1,2,3,4,5]
for i in list1:
rtn = classA.myFoo1(i)
Which would give you a final rtn value of 30 when you exit the for loop.
I'm trying to pass information back and forth between 2 scripts. In one, we obtain a user input, in the other some modification is done to the user input, then back to the first one, we print out that modification.
#del2
def fun():
return int(user_input)+1
#script to run
user_input=input('some number')
from del2 import fun
print(fun())
So when we run our script, the user gives some input, the next line then runs the other script, which adds a value of 1 to the user inputted value, and then we print out that modified value. However, it appears you can't define a variable in one script, and have that defined variable transfer over to another script. Thus, I get this error when I try the above: NameError: name 'user_input' is not defined. I've tried to look at other posts regarding this, but they use tkinter and all are a bit too complicated/over my head to understand. So I made a very basic simple example to try and understand how this all works.
Edit:
I don't want to make another post, since its regarding the same issue. If I have to define every input used for every function, then it becomes quite crowded if you have multiple inputs. I.E.
#del2
def fun(user_input):
return int(user_input)+1
def fun2(user_input2):
return int(user_input2)+1
def fun3(user_input3):
return int(user_input3)+1
def fun4(user_input4):
return int(user_input4)+1
def fun5(user_input,user_input2,user_input3,user_input4):
return fun(user_input)+fun2(user_input2)+fun3(user_input3)+fun4(user_input4)
#script to run
user_input=input('some number')
user_input2=input('some number')
user_input3=input('some number')
user_input4=input('some number')
from del2 import fun5
print(fun5(user_input,user_input2,user_input3,user_input4))
Is there a better way to do this, so fun5 doesn't become extremely long if you have multiple inputs.
You need to define fun so it takes the variable as a parameter: def fun(user_input) then pass that variable to the imported function.
Also if you want user_inputs value to change after you call your fun() function you need to something like this:
#del2
def fun(user_input):
return int(user_input) + 1
#script to run
user_input = input('some number')
from del2 import fun
user_input = fun(user_input)
print(user_input)
Edit:
The fun() function isnt for just user_input. So you can use the same fun() function for another variables.
#del2
def fun(any_input): # i changed the variables name just to be clear
return int(any_input) + 1
#script to run
user_input = input('some number')
user_input2 = input('some number')
from del2 import fun
user_input = fun(user_input)
user_input2 = fun(user_input2)
print(user_input + ", " + user_input2)
and you can add the input variables to an array and do something like
#del2
def fun(any_input):
return int(any_input) + 2
def fun1(any_input):
return int(any_input) * 2
def fun2(any_input):
return int(any_input) // 2
def fun3(any_input):
return int(any_input) - 2
def fun5(input_array):
functions = [fun, fun1, fun2, fun3]
final = 0
if len(input_array) != 4:
raise Exception("Not enough functions for inputs")
for i in range(len(input_array)):
final += functions[i](input_array[i])
return final
#script to run
user_inputs = []
user_inputs.append(input('some number 0: ')) #you can use a for loop here too
user_inputs.append(input('some number 1: '))
user_inputs.append(input('some number 2: '))
user_inputs.append(input('some number 3: '))
from del2 import fun5
user_inputs = fun5(user_inputs)
print(user_inputs)
You can do this using the global keyword and a global variable within the imported module that is accessed by the different functions. Taking a simpler example that just adds or subtracts from a globally stored total:
# tally.py
total = 0
def add(n):
global total
total += n
def subtract(n):
global total
total -= n
# test_tally.py
import tally
tally.add(5)
tally.subtract(1)
print(tally.total)
However, global variables are bad. We do not generally think in terms of passing data back and forth between modules. The imported module is executed in its entirety at the time of importing, so data can only be passed to functions or other objects within the imported module.
Instead, modules often include classes, which can be used to generate objects that can store state. Data can be passed to these objects and stored within them. The objects can then operate upon the data and return different results by calling different methods of the object. This would be written like this:
# tally.py
class Tally(object):
def __init__(self):
self.total = 0
def add(self, n):
self.total += n
def subtract(self, n):
self.total -= n
# test_tally.py
from tally import Tally
tally = Tally()
tally.add(3)
tally.subtract(4)
print(tally.total)
I am a bit confused over this.
I have a function. Inside that function it asks a number of questions, one is the following based on the number of gardens they have - so if they say they have 2 gardens it will ask this question twice and should add the 100 twice to the calculation:
gardens = int(input("How many gardens do you have: "))
def gard():
calc = 0
gardener = input("Do you need a gardener? Y or N ")
if gardener == "Y" or gardener == "y":
calc = calc + 100
else:
calc = calc + 0
for i in range(gardens):
gard()
How do I keep a running total outside of the function? When I put print(calc) inside the function it just displays 100 each time they say Y but doesn't add it together.
Edited to include updated code:
The eMake section (the IF statement) returns a value - but it only ever returns the first in the calculation at the end?
Also struggling to do the area section since there are numerous ws. It only stores the last value for the variable.
noGard = int(input("Enter number of gards which require cleaning: "))
#Defining variables
Calc = 0
Area = 0
emCalc = 0
#Room information
def GInfo():
global Calc
global Area
gName = input("Enter gard name: ")
noW = int(input("How many w are in the "+gName + "? "))
#Repeats the questions for each W
for i in range(noW):
Height = float(input("What is the w height of in metres? "))
Width = float(input("What is the w width in metres? "))
Area = Height * Width
#Asks if w needs to be removed
w = input("Does w need removing? Y or N ")
if w == "Y" or w == "y":
Calc = Calc + 70
else:
Calc = Calc + 0
print (" ")
#Returns the values
return Calc
return Area
#Calculate Sarea
#Identifying e
def e():
global emCalc
#eMake
eMake = input("What make of e - HH or NN? ")
if eMake == "HH" or "hh":
emCalc = emCalc + 200
elif eType == "NN" or "nn":
emCalc = emCalc + 50
else: print("You have entered an invalid e make")
#Returns the values
return emCalc
#Repeats the g information questions for each g
for i in range(noGard):
GInfo()
# Runs the E function
e()
#Print total without VAT
total = Calc + emCalc
print(total)
print(Area)
Your function should return the calculated value.
def gard():
...
return calc
total = 0
for _ in range(gardens):
total += gard()
print 'Total: ', total
The whole point of functions, really, is that they take parameters and return values. (Some languages, although not Python, refer to functions that don't do this as "procedures".)
That is what you need to do here: your gard function needs to return the value of calc. You probably don't want to actually do the addition inside the function itself, but if you did, you would also need to accept the current value of calc as a parameter, which you would pass in from your for loop.
Functions, in the strictest sense, do not have state. When writing functional programs, one typically aims to keep their functions pure, meaning that the result of the function does not depend on anything but its inputs and does not cause observable side effects.
But Python is not a purely functional language. It is an object-oriented procedural language which models functions as objects, and objects can be stateful. So you can do what you're aiming to, if you don't take the word "function" too literally.
The Right Thing™
Create a class which models your data and the operations on it:
>>> class F(object):
... def __init__(self):
... self.x = 0
... def f(self):
... self.x += 1
... return self.x
...
>>> my_f = F()
>>> my_f.f()
1
>>> my_f.f()
2
Fun and naughty ways
Add state to the function object, taking advantage of the fact that function bodies aren't executed until the function is called:
>>> def f():
... f.x += 1
... return f.x
...
>>> f.x = 0
>>> f()
1
>>> f()
2
If you want to do this transparently (that is, make it so that you don't have to add this state to the function right after defining it) you can close over the state by having a function create a function:
>>> def g():
... def func():
... func.x += 1
... return func.x
... func.x = 0
... return func
...
>>> f = g()
>>> f()
1
>>> f()
2
To take it a step further, create a decorator so you don't have to do any assignments after defining the function at all:
>>> def with_x(func):
... func.x = 0
... return func
...
>>> #with_x
... def f():
... f.x += 1
... return f.x
...
>>> f()
1
>>> f()
2
Or you can just use global to let a function refer to something outside of its local scope, not taking advantage of the fact that functions are objects:
>>> x = 0
>>> def f():
... global x
... x += 1
... return x
...
>>> f()
1
>>> f()
2
>>> x
2
Updates for your edit
Since you went with global I'll first refer you to a good question that explains global. Using global variables in a function other than the one that created them
Now, as for your particular problems:
The eMake section (the IF statement) returns a value - but it only ever returns the first in the calculation at the end?
Sure, there are a couple problems here and one of them is definitely a common one for beginners. or takes higher precedence than == so your condition parses like this:
if (eMake == "HH") or ("hh"):
This gets people all the time. In Python, if a value isn't a boolean and you put it in a conditional statement, it gets evaluated as a boolean using a series of truthiness rules. In this case a non-empty string is considered True so you are basically saying if (eMake == "HH") or True.
To fix this, fix the right-hand side of the condition:
if (eMake == "HH") or (eMake == "hh"):
By the way, you probably meant elif (eMake == "NN") or (eMake == "nn"): instead of elif eType == "NN" or "nn": because you never defined eType (and for the reason above, too.) If you type nn there you'll get an exception.
Also struggling to do the area section since there are numerous ws. It only stores the last value for the variable.
This is because you repeatedly assign to the same variable with Area = Height * Width. Since Area is global, it's the same variable every time you call GInfo(). If it wasn't global it would be a new variable every time you called the function, but then you would need to return it and assign the return value to a variable in order to save the value. Otherwise it would disappear since it was never assigned to anything.
Now, I don't know what you are trying to do with the areas you're calculating. Do you want to keep them separate or sum them together?
If you want to keep them separate, you'll need to use a data structure. In this case, you'd definitely want to use a list. Using the append() method of lists, you can add an item to the list. So it would look something like this:
areas = [] # empty list
def GInfo():
global areas
# the stuff before the loop
for i in range(noW):
Height = float(input("What is the w height of in metres? "))
Width = float(input("What is the w width in metres? "))
areas.append(Height * Width)
# the stuff after the loop
If you want to sum them together, just make sure you add each individual area calculation to the previous result, just like you did with Calc:
Area += Height * Width
One more thing: your GInfo() function is only returning Calc and not Area as well. Functions can only return one value. In the mathematical sense, a function is a many-to-one mapping between two sets. So in Python, a function ends at the return statement. Nothing else gets executed after that.
In order to get both the value of Calc as well as the value of Area from the return value of GInfo(), you will have to return a data structure. Usually this would be a tuple.
return (Calc, Area)
But your code doesn't assign the return value of GInfo() to anything. Instead, it uses the global declaration to change the value of the global variables. So there shouldn't be an issue here.
Made up the following code:
import math
def z(a,b,s):
import math
elements = list()
for i in range(a,b):
elements.append(i**-s)
return elements
f = math.fsum(elements)
print (f)
the problem is that I am getting back the list with "return elements" but not the "math.fsum(elements)
what am I doing wrong ?
I've fixed a few things, and made a few suggestions:
import math # You should be aware that python has a builtin sum function
def z(a,b,s):
#import math << There is no need to import the module twice, so I've commented it, meaning it won't execute
elements = list() # Unconventional, but it works - it's more common to just create a literal empty list like so: elements = []
for i in range(a,b):
elements.append(i**-s)
f = math.fsum(elements)
return elements, f # Here we're returning both your list AND the sum in a "tuple" (assuming you want to return both)
# Note that once the return function executes, the interpreter exits the function, and nothing else in the function will be executed.
elements, f = z(5, 10, 3) # Here we're calling the function, and "unpacking" the two things we returned from the tuple into two variables.
print f # This will print out your sum.