I have several pre-defined functions in a dictionary:
dict = {
'test1':test1(),
'test2':test2(),
'test3':test3()
}
At this point I already have a question: after creating the dictionary these functions run automatically - why is that and how can I avoid it?
Ultimately, my goal is to type in e.g. "test2" and get the function executed (just the one in a controlled manner, not everything at once like above). First I wanted to use eval, but everyone advised against it, which I understand now. But what is the alternative? I tried
def select_function():
try:
return dict[input("Type in function ")]
except KeyError:
raise ValueError('Invalid input!')
select_function()
as well as just
dict.get(input("Type in function "), 'Invalid input!')
But both return an empty line if I type in the correct function. If I type in a wrong one I get my error message, therefore my command should work in general. I also know my functions work because, as I said, they get executed after I create the dictionary and they only print a greeting (a different one for each function for testing).
Did I do something wrong? Is there some other way to call functions without eval()?Thanks in advance.
Do it like
dict = {
'test1':test1,
'test2':test2,
'test3':test3
}
Then
return dict[input("Type in function")]
If you want to call that function, Just
return dict[input("Type in function")]()
Related
I'm trying to store a function in a list, retrieve the function from the list later, and then call on that function. This is basically what I want to do, without any specifics. It doesn't show my purpose, but it's the same issue.
elements: list = [] # List meant to contain a tuple with the name of the item and the function of the item.
def quit_code():
exit()
element.append(("quit", quit_code))
Now, somewhere else in the code, I want to be able to use an if statement to check the name of the item and, if it's the right one at that time, run the function.
user_input = "quit" # For brevity, I'm just writing this. Let's just imagine the user actually typed this.
if elements[0][0] == user_input:
#This is the part I don't understand so I'm just going to make up some syntax.
run_method(elements[0][1])
The method run_method that I arbitrarily made is the issue. I need a way to run the method returned by elements[0][1], which is the quit_code method. I don't need an alternative solution to this example because I just made it up to display what I want to do. If I have a function or object that contains a function, how can I run that function.
(In the most simplified way I can word it) If I have object_a (for me it's a tuple) that contains str_1 and fun_b, how can I run fun_b from the object.
To expand on this a little more, the reason I can't just directly call the function is because in my program, the function gets put into the tuple via user input and is created locally and then stored in the tuple.
__list_of_stuff: list = []
def add_to_list(name, function):
__list_of_stuff.append((name, function))
And then somewhere else
def example_init_method():
def stop_code():
exit()
add_to_list("QUIT", stop_code())
Now notice that I can't access the stop_code method anywhere else in the code unless I use it through the __list_of_stuff object.
Finally, It would be nice to not have to make a function for the input. By this, I mean directly inserting code into the parameter without creating a local function like stop_code. I don't know how to do this though.
Python treats functions as first-class citizens. As such, you can do things like:
def some_function():
# do something
pass
x = some_function
x()
Since you are storing functions and binding each function with a word (key), the best approach would be a dictionary. Your example could be like this:
def quit_code():
exit()
operations = dict(quit=quit_code)
operations['quit']()
A dictionary relates a value with a key. The only rule is the key must be immutable. That means numbers, strings, tuples and other immutable objects.
To create a dictionary, you can use { and }. And to get a value by its key, use [ and ]:
my_dictionary = { 'a' : 1, 'b' : 10 }
print(my_dictionary['a']) # It will print 1
You can also create a dictionary with dict, like so:
my_dictionary = dict(a=1, b=10)
However this only works for string keys.
But considering you are using quit_code to encapsulate the exit call, why not using exit directly?
operations = dict(quit=exit)
operations['quit']()
If dictionaries aren't an option, you could still use lists and tuples:
operations = [('quit',exit)]
for key, fun in operations:
if key == 'quit':
fun()
I am trying to replace a largish if-elif block in python with something a bit more like java switch. My understanding is this should be a bit faster and we are parsing lots of data so if I can get speed improvement I will take it. However, what is happening is the code is always acting as if the key is 'deposits' even for entries that are not. The "func =" line is there to validate I am getting things correctly. I will probably not return a result to func since my goal is to fill a list with results.
What am I doing wrong that the switcher.get always finds a match even when one does not exist?
`def parsePollFile(thisFile):
line = ''
switcher = {
'deposits': deposits(line)
}
try:
reader = csv.reader(open(thisFile, 'r'))
for line in reader:
try:
if line[2] == "D":
func = switcher.get(line[0], lambda: 'invalid key')
print('key: {} -- {}\n'.format(line[0],func))
except IndexError:
continue
except Exception as e:
print("exception {}\n".format(e))
`
Your problem is that the code
switcher = {'deposits': deposits(line)}
Doesn't create a key in your dictionary with the value being the deposits function object. 'deposits': deposits(line) actually runs the deposits function, and stores the return value as the value of the 'deposits' key. You need to store a function object in the dictionary.
Since your function takes arguments, this is a bit tricky. There are several ways around this problem, but perhaps the simplest is to wrap your function call in another function
switcher = {'deposits': lambda: deposits(line)}
You would then use the dictionary like so
func = switcher.get(line[0], lambda: 'invalid key')
func()
My solution resulted from both the comment and the answer. I changed the 'deposits': deposits(line) to be 'deposits':deposits and then I run the func(line) when a match is found.
Thank you to the answers. I did not realize I was actually running the method instead of defining the value.
I'm new to Python and using Anaconda (editor: Spyder) to write some simple functions. I've created a collection of 20 functions and saved them in separate .py files (file names are the same as function names).
For example
def func1(X)
Y=...
return Y
I have another function that takes as input a function name as string (one of those 20 functions), calls it, does some calculations and return the output.
def Main(String,X)
Z=...
W=String(Z)
V=...
return V
How can I choose the function based on string input?
More details:
The Main function calculates the Sobol Indices of a given function. I write the Main function. My colleagues write their own functions (each might be more than 500 lines of codes) and just want to use Main to get the Sobol indices. I will give Main to other people so I do NOT know what Main will get as a function in the future. I also do not want the user of Main to go through the trouble of making a dictionary.
Functions are objects in Python. This means you can store them in dictionaries. One approach is to dispatch the function calls by storing the names you wish to call as keys and the functions as values.
So for example:
import func1, func2
operation_dispatcher = {
"func1": getattr(func1, "func1"),
"func2": getattr(func2, "func2"),
}
def something_calling_funcs(func_name, param):
"""Calls func_name with param"""
func_to_call = operation_dispatcher.get(func_name, None)
if func_to_call:
func_to_call(param)
Now it might be possible to generate the dispatch table more automatically with something like __import__ but there might be a better design in this case (perhaps consider reorganizing your imports).
EDIT took me a minute to fully test this because I had to set up a few files, you can potentially do something like this if you have a lot of names to import and don't want to have to specify each one manually in the dictionary:
import importlib
func_names = ["func1", "func2"]
operation_dispatch = {
name : getattr(importlib.import_module(name), name)
for name in func_names}
#usage
result = operation_dispatch[function_name](param)
Note that this assumes that the function names and module names are the same. This uses importlib to import the module names from the strings provided in func_names here.
You'll just want to have a dictionary of functions, like this:
call = {
"func1": func1,
"functionOne": func1,
"func2": func2,
}
Note that you can have multiple keys for the same function if necessary and the name doesn't need to match the function exactly, as long as the user enters the right key.
Then you can call this function like this:
def Main(String,X)
Z=...
W=call[String](Z)
V=...
return V
Though I recommend catching an error when the user fails to enter a valid key.
def Main(String,X)
Z=...
try:
W=call[String](Z)
except KeyError:
raise(NameError, String + " is not a valid function key")
V=...
return V
I have router that is deciding which function to call based upon user input (uses ConfigParser) and then tries to decide which function to call.
def SomethingElse():
print 'hello'
def UploadDirectory():
print 'hi'
def router(config):
if config.has_option('job', 'Some_Task'):
taskName = config.get('job', 'Some_Task')
# taskName is now 'UploadDirectory'
###execute the UploadDirectory function
###execute something else if something else, etc
So what is the way to write this in python? If I prebuilt a map of functions to strings, can i execute them that way?
How would you write this?
Yep, building a map of strings to function names is perfectly valid:
task_map = {
'upload': UploadDirectory,
'something': SomethingElse,
}
And execute as:
task_map[task_name]()
Aside: try to follow PEP-8, the python style guide; it helps make your code more readable to all other Python programmers. Specifically in this case, prefer underscore_separated function names instead of LeadingCaps.
Another hacky way to do it is to use globals(), if you're not running just by importing the router function:
globals()[taskName]()
I wonder how to correctly use python 2.7 callback functions.
I have some callback functions from Cherrypy auth examples in my code.
(These callbacks return a function that can evaluate to True or False, depending on the logged in user being in a group or not.)
I wonder if a callback is executed or not if I write a piece of code like this:
Given the definition from the library is:
def member_of(groupname):
def check():
if groupname == 'admin':
if cherrypy.request.login == 'joe':
return True
if cherrypy.request.login == 'toni':
return True
return False
return False
# .... (other groups checked in the same way)
return check # returns a callback function from my understanding?
How can I apply and execute the callback in my code?
If I put it like this:
if member_of('admin'):
do_something()
else:
do_something_else()
Will this execute the calllback and check for the admin group? Or will it find out if the value of "member_of" is a function definition and a function definition is probably always a "True" value (or maybe a False value) but both are wrong, because it needs to be executed
Can you enlighten me on this? How can I make sure a callback is executed? An how can I pass it around as it is?
In python, like in many other languages, a variable can also contain a function and you can pass them around like other variables that contain e.g. numbers or strings.
CherryPy's member_of function itself does return a function in your example.
I am explaining it in simple steps:
If you write member_of() it returns the result of the function member_of() which is the function with the name check in this case.
cb_function = member_of('admin')
At this point the variable cb_function holds the result of calling the function member_of, and in the last line member_of returns check, which was defined within the function member_of as another function!
You have to call the first result again, because you can and you have to treat it in almost the same way as a local function, that you defined in the current context, to get the final result, by doing something like:
my_result = cb_function()
And then you would continue and use the result. For example you could check its boolean value:
if my_result:
# do something
...
The 3 steps from above together can be written shorter:
cb_function = member_of('admin')
if cb_function():
# do something
...
Or even shorter:
if member_of('admin')():
# do something
...
At first it may appear a little strange in python to have the double ()(), but if you think about it for a while it makes sense.
If you execute it, it is plain simple.
member_of() will return method object check.
you have to execute to get result by doing something like if member_of('admin')():
or,
k=member_of('admin')
if k():
To do your task.