I am trying to make a menu of options in python where if the user selects a number a different function is executed:
def options(x):
return {
1: f1(),
2: f2()
}[x]
def f1():
print "hi"
def f2():
print "bye"
However, well I call
options(1)
I get:
hi
bye
and same when I call options(2)
What is going on?
You are invoking the functions instead of assiging them against the keys
def f1():
print "hi"
def f2():
print "bye"
functions = {1: f1, 2: f2} # dict of functions (Note: no parenthesis)
def options(x):
return functions[x]() # Get the function against the index and invoke it
options(1)
# hi
options(2)
# bye
Your dictionary is built with the return values of the functions; don't call the function until after picking it from the dict:
def options(x):
return {
1: f1,
2: f2
}[x]()
Now you are storing just a reference to the functions in the dictionary, and call the selected function after retrieving it.
Demo:
>>> def f1():
... print "hi"
...
>>> def f2():
... print "bye"
...
>>> def options(x):
... return {
... 1: f1,
... 2: f2
... }[x]()
...
>>> options(1)
hi
>>> options(2)
bye
Replace print with return and return with, then it will work. Or use thefourtheye version.
The problem is that you call the functions (with ()) while you are building the dictionary. Leave the parens off and apply them later only after getting the value from the dictionary:
def options(x):
return {
1: f1,
2: f2
}[x]()
Related
I am trying to create a list of functions in my program in order to use the random module to randomly choose. in theory it look and work with this
import random
def test1():
print("1st function")
def test2():
print("2nd function")
def test3():
print("3rd function")
def test_func():
test_list = [test1(), test2(), test3()]
apple = random.choice(test_list)
return print(apple)
test_func()
the result of this is it prints out test_list and prints "NONE" for apple is there a way to get it to randomly pick a function and only print that function.
you should add function reference to the list and call the function after.
def test_func():
test_list = [test1, test2, test3]
apple = random.choice(test_list)()
The problem here is that you are assigning the list the return values of the functions you created. Since they do not have a return value, it will be None.
What you need to do is assign the function itself by removing the parenthesis. You would also need to call the apple function by adding the parenthesis to it, not by printing it. So, your code will look like this:
import random
def test1():
print("1st function")
def test2():
print("2nd function")
def test3():
print("3rd function")
def test_func():
test_list = [test1, test2, test3]
apple = random.choice(test_list)
apple()
test_func()
def test1():
print("1st function")
#This returns "None"
The reason you are getting "None" printed to console is because you are printing the function, which does return a NoneType. Return defaults to None if not specified. To make it only print the desired function remove the line return print(apple)
You would also want to store references to your functions:
test_list = [test1, test2, test3]
so that they are not executed. Then you can run apple() to execute them in your main function.
Yes, just don't call the functions when you put them in the list:
import random
def test1():
print("1st function")
def test2():
print("2nd function")
def test3():
print("3rd function")
def test_func():
test_list = [test1, test2, test3]
apple = random.choice(test_list)
return apple() #won't return anything due to it being a print function
test_func()
Is it possible to pass parameters to a function that it is call through it callbacks directory in python?
I was trying to do something like this and wishing to print "hello" at the end of the execution.
def f1(text):
print text
pass
def f2():
pass
selector_by_type = {
1: f1,
2: f2
}
selector = selector_by_type.get(1)
selector("hello")
def other_new_function():
print "HELLO"
print "Start", other_new_function(), "Stop"
The output of this program is:
Start HELLO
None Stop
Why is NONE being showed in the output?
Because you're printing "HELLO", and not returning it.
Because your function does not return anything, it defaults to returning None. Hence, the None that appears.
Change:
def other_new_function():
print "HELLO"
To:
def other_new_function():
return "HELLO"
There's a big difference to returning and printing something from a function:
>>> def func():
... print 1
...
>>> def func2():
... return 1
...
>>> myvar = func()
1 # Printed
>>> myvar2 = func2() # Returned to a variable
>>> print myvar
None
>>> print myvar2
1
Because function 1 prints the value, it never gets returned to a variable.
def other_new_function():
print "HELLO"
returns NoneType (which gets printed as 'None') since you dont explicitly return a value. What you probably want to do is:
def other_new_function():
return "HELLO"
I'm working on a script that takes a few minutes to run, and would like to provide some output to the user about its progress. Unfortunately i'm exceedingly lazy. what I'd like to do is write a function without the logging, and then apply a decorator to it which steps through the function and prints each line before executing that line. Basically what I'm looking for is a loggingdecorator such that:
>>> #loggingdecorator
... def myfunction():
... foo()
... bar()
... baz()
>>> myfunction()
Starting myfunction
foo() ... [OK]
bar() ... [OK]
baz() ... [OK]
myfunction Done!
Here's what I've tried so far:
import sys
def logging_tracer(frame, event, arg):
def local_tracer(local_frame, event, arg):
if frame is local_frame:
print frame.f_code.co_name, event, arg
print frame.f_code.co_name, event, arg
return local_tracer
def loggingdecorator(func):
def _wrapper():
old_trace_function = sys.gettrace()
sys.settrace(logging_tracer)
try:
result = func()
except:
raise
else:
return result
finally:
sys.settrace(old_trace_function)
return _wrapper
Unfortunately, this prints a bit too much; it follows function calls and prints them out, line by line as well (well, this doesn't actually print the source line, existing answers using inspect, combined with stuff on the frame object in the trace function would do it), but I'm a bit stumped as to how the logging_tracer unless the function in question is actually decorated.
So here's what I came up with. #Corley Brigman's comment got me started in the right direction. This is a bit hackey, sys.gettrace/settrace are rather promenently documented as "CPython implementation details", and so this solution should not be expected to work in other implementations. That said, it seems to work out pretty well. The tracing functionality in cpython does not provide any notification of "line finished executing", so the [ok] from my question doesn't really make any sense.
Fixing the recursive tracing issue is just a simple matter of keeping a cache of the functions that were decorated, and then only produce output if the frame being traced is from a function that was decorated.
import inspect
import sys
def logging_tracer(frame, event, arg):
lines, firstline = inspect.getsourcelines(frame)
def local_tracer(local_frame, event, arg):
if event == 'line' and frame is local_frame:
print event, frame.f_lineno,'\t', lines[frame.f_lineno - firstline]
#print event, lines[frame.f_lineno - firstline]
#print frame.f_code.co_name, frame.f_lineno, event, arg
if frame.f_code in LOG_THESE_FUNCTIONS:
print event, frame.f_lineno,'\t', lines[frame.f_lineno - firstline + (event == 'call')]
#print frame.f_code.co_name, event, arg
return local_tracer
else:
return None
LOG_THESE_FUNCTIONS = set()
def loggingdecorator(func):
LOG_THESE_FUNCTIONS.add(func.func_code)
def _wrapper():
old_trace_function = sys.gettrace()
sys.settrace(logging_tracer)
try:
result = func()
except:
raise
else:
return result
finally:
sys.settrace(old_trace_function)
return _wrapper
Here's an ugly example that works if there's only one indentation level:
import inspect
def myDec(func):
temp = list(inspect.getsourcelines(func)[0])
temp.append(' print("{} Done!")\n'.format(func.__name__))
for index in range(len(temp)-2, 0, -1):
temp.insert(index+1, " print('''{}...[OK]''')\n".format(temp[index].strip().rstrip("\n")))
temp.insert(1, ' print("Starting {}")\n'.format(func.__name__))
temp = "".join(temp)
exec(temp)
return locals()[func.__name__]
def foo():
a = 4+5
list_int = range(100)
foo = myDec(foo)
foo()
Really ugly though...
You can do something like this:
>>> class loggingdecorator:
... def __init__(self, func):
... self.func = func
... def __call__(self):
... print "Entering", self.func.__name__
... self.func()
... print "Exited", self.func.__name__
...
Then with each of your functions:
>>> #loggingdecorator
... def func1():
... print "Hello from func1(), how are you doing?"
...
>>> #loggingdecorator
... def func2():
... print "Hello from func2(), Whaddup Dawg...?"
...
>>> func1()
Entering func1
Hello from func1(), how are you doing?
Exited func1
>>> func2()
Entering func2
Hello from func2(), Whaddup Dawg...?
Exited func2
Found the example from this page
I am trying to use functional programming to create a dictionary containing a key and a function to execute:
myDict={}
myItems=("P1","P2","P3",...."Pn")
def myMain(key):
def ExecP1():
pass
def ExecP2():
pass
def ExecP3():
pass
...
def ExecPn():
pass
Now, I have seen a code used to find the defined functions in a module, and I need to do something like this:
for myitem in myItems:
myDict[myitem] = ??? #to dynamically find the corresponding function
So my question is, How do I make a list of all the Exec functions and then assign them to the desired item using the a dictionary? so at the end I will have myDict["P1"]() #this will call ExecP1()
My real problem is that I have tons of those items and I making a library that will handle them so the final user only needs to call myMain("P1")
I think using the inspect module, but I am not so sure how to do it.
My reason to avoid:
def ExecPn():
pass
myDict["Pn"]=ExecPn
is that I have to protect code as I am using it to provide a scripting feature within my application.
Simplify, simplify, simplify:
def p1(args):
whatever
def p2(more args):
whatever
myDict = {
"P1": p1,
"P2": p2,
...
"Pn": pn
}
def myMain(name):
myDict[name]()
That's all you need.
You might consider the use of dict.get with a callable default if name refers to an invalid function—
def myMain(name):
myDict.get(name, lambda: 'Invalid')()
(Picked this neat trick up from Martijn Pieters)
Simplify, simplify, simplify + DRY:
tasks = {}
task = lambda f: tasks.setdefault(f.__name__, f)
#task
def p1():
whatever
#task
def p2():
whatever
def my_main(key):
tasks[key]()
Not proud of it, but:
def myMain(key):
def ExecP1():
pass
def ExecP2():
pass
def ExecP3():
pass
def ExecPn():
pass
locals()['Exec' + key]()
I do however recommend that you put those in a module/class whatever, this is truly horrible.
If you are willing to add a decorator for each function, you can define a decorator which adds each function to a dictionary:
def myMain(key):
tasks = {}
def task(task_fn):
tasks[task_fn.__name__] = task_fn
#task
def ExecP1():
print(1)
#task
def ExecP2():
print(2)
#task
def ExecP3():
print(3)
#task
def ExecPn():
print(4)
tasks['Exec' + key]()
Another option is to place all the functions under a class (or in a different module) and use getattr:
def myMain(key):
class Tasks:
def ExecP1():
print(1)
def ExecP2():
print(2)
def ExecP3():
print(3)
def ExecPn():
print(4)
task = getattr(Tasks, 'Exec' + key)
task()
# index dictionary by list of key names
def fn1():
print "One"
def fn2():
print "Two"
def fn3():
print "Three"
fndict = {"A": fn1, "B": fn2, "C": fn3}
keynames = ["A", "B", "C"]
fndict[keynames[1]]()
# keynames[1] = "B", so output of this code is
# Two
You can just use
myDict = {
"P1": (lambda x: function1()),
"P2": (lambda x: function2()),
...,
"Pn": (lambda x: functionn())}
myItems = ["P1", "P2", ..., "Pn"]
for item in myItems:
myDict[item]()
This will call methods from dictionary
This is python switch statement with function calling
Create few modules as per the your requirement.
If want to pass arguments then pass.
Create a dictionary, which will call these modules as per requirement.
def function_1(arg):
print("In function_1")
def function_2(arg):
print("In function_2")
def function_3(fileName):
print("In function_3")
f_title,f_course1,f_course2 = fileName.split('_')
return(f_title,f_course1,f_course2)
def createDictionary():
dict = {
1 : function_1,
2 : function_2,
3 : function_3,
}
return dict
dictionary = createDictionary()
dictionary[3](Argument)#pass any key value to call the method
#!/usr/bin/python
def thing_a(arg=None):
print 'thing_a', arg
def thing_b(arg=None):
print 'thing_b', arg
ghetto_switch_statement = {
'do_thing_a': thing_a,
'do_thing_b': thing_b
}
ghetto_switch_statement['do_thing_a']("It's lovely being an A")
ghetto_switch_statement['do_thing_b']("Being a B isn't too shabby either")
print "Available methods are: ", ghetto_switch_statement.keys()
Often classes are used to enclose methods and following is the extension for answers above with default method in case the method is not found.
class P:
def p1(self):
print('Start')
def p2(self):
print('Help')
def ps(self):
print('Settings')
def d(self):
print('Default function')
myDict = {
"start": p1,
"help": p2,
"settings": ps
}
def call_it(self):
name = 'start'
f = lambda self, x : self.myDict.get(x, lambda x : self.d())(self)
f(self, name)
p = P()
p.call_it()
class CallByName():
def method1(self):
pass
def method2(self):
pass
def method3(self):
pass
def get_method(self, method_name):
method = getattr(self, method_name)
return method()
callbyname = CallByName()
method1 = callbyname.get_method(method_name)
```
def p1( ):
print("in p1")
def p2():
print("in p2")
myDict={
"P1": p1,
"P2": p2
}
name=input("enter P1 or P2")
myDictname
You are wasting your time:
You are about to write a lot of useless code and introduce new bugs.
To execute the function, your user will need to know the P1 name anyway.
Etc., etc., etc.
Just put all your functions in the .py file:
# my_module.py
def f1():
pass
def f2():
pass
def f3():
pass
And use them like this:
import my_module
my_module.f1()
my_module.f2()
my_module.f3()
or:
from my_module import f1
from my_module import f2
from my_module import f3
f1()
f2()
f3()
This should be enough for starters.