How can I create chain of callbacks in python? - python

In javascript I can do following:
var some = 100;
var param1 = 1;
func1(param1, function(res1) {
var param2 = res1 + some;
func2(param2, function(res2) {
// ...
});
});
In php same:
$some = 100;
$param1 = 1;
func1($param1, function($res1) use ($some) {
$param2 = $res1 + $some;
func2($param2, function($res2) {
// ...
});
});
How can I do same thing in python?
................................................

Pass functions as arguments.
some = 100
def callback1(res1):
param2 = res1 + some
func2(param2, callback2)
def callback2(res2):
...
param1 = 1
func1(param1, callback1)

I see that you tagged asynchronous as well. Python is NOT asynchronous. But python functions are also first class objects just like javascript and php. So, you can do the same thing in python as well.
def func1(data, nextFunction = None):
print data
if nextFunction:
nextFunction()
def func(data, nextFunction = None):
print data
nextFunction(data * 10)
func(1, func1)
Output
1
10
Inline function definitions are restricted in python but it is still possible with lambda functions. For example,
data = ["abcd", "abc", "ab", "a"]
print sorted(data, key = lambda x: len(x)) # Succinctly written as key = len
Output
['a', 'ab', 'abc', 'abcd']

Functions are first class objects in Python, and you can nest them as well.
EG:
#!/usr/local/cpython-3.3/bin/python
some = 100
param1 = 1
def func1(param1, function):
param2 = res1 + some;
def func2(param2, function):
pass
func2(param2, function)

Decorators are just syntactic wrappers for "thing that can execute arbitrary code before and after another function." That's what you're doing with a callback, and hey: flat is better than nested.
def func1(fn):
def wrapped(arg):
return fn(arg+1)
return wrapped
def func2(fn):
def wrapped(arg):
return fn(arg+2)
return wrapped
#func1
#func2
def func3(x):
return x + 3
print(func3(1))
#prints 7

Related

How to run a specific function using a code within python [duplicate]

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.

How to replace part of a function call with variable in Python?

I have a dictionary with some function expressions as values. Each of the values are very similar, except the part in the middle. In the following example, only earn_yld, free_cash_flow_yield and eps_growth are different in the long formula.
factor_bql = {
"ltm_earnings_yield": bq.func.dropna(bq.data.earn_yld(as_of_date=bq.func.RANGE(params['start'],params['end']))),
"ltm_fcf_yield": bq.func.dropna(bq.data.free_cash_flow_yield(as_of_date=bq.func.RANGE(params['start'],params['end']))),
'ltm_eps_growth': bq.func.dropna(bq.data.eps_growth(as_of_date=bq.func.RANGE(params['start'],params['end'])))
}
Is there any way to write a function or variable to simplify the values of the dictionary to something like
def simple_formula(xyz):
... ...
factor_bql = {
"ltm_earnings_yield": simple_formula('earn_yld'),
"ltm_fcf_yield": simple_formula('free_cash_flow_yield'),
'ltm_eps_growth': simple_formula('eps_growth')
}
I'd do this in following way:
def simple_formula(fn):
return bq.func.dropna(fn(as_of_date=bq.func.RANGE(params['start'],params['end'])))
factor_bql = {
"ltm_earnings_yield": simple_formula(bq.data.earn_yld),
"ltm_fcf_yield": simple_formula(bq.data.free_cash_flow_yield),
'ltm_eps_growth': simple_formula(bq.data.eps_growth)
}
So, functions themselves (not their names) are parameters of simple_formula.
You can use the globals function to call a function in the current module by the string representation of its name.
def func1(bar):
return "func1" + str(bar)
def func2(bar):
return "func2" + str(bar)
def simple_formula(func_name):
return globals()[func_name](bar="baz")
factor_bql = {
"key1": simple_formula("func1"),
"key2": simple_formula("func2"),
}
print(factor_bql["key2"]) # prints "func2baz"
Assuming bq.data is some object:
def simple_formula(xyz):
method = getattr(bq.data, xyx) # get a method by its name
return bq.func.dropna(method(as_of_date=bq.func.RANGE(params['start'],params['end'])))

Decorator: Maintain state

I need to compose information regarding the given information like what parameter the given function takes etc. The example what I would like to do is
#author("Joey")
#parameter("name", type=str)
#parameter("id", type=int)
#returns("Employee", desc="Returns employee with given details", type="Employee")
def get_employee(name, id):
//
// Some logic to return employee
//
Skeleton of decorator could be as follows:
json = {}
def author(author):
def wrapper(func):
def internal(*args, **kwargs):
json["author"] = name
func(args, kwargs)
return internal
return wrapepr
Similarly, parameter decorator could be written as follows:
def parameter(name, type=None):
def wrapper(func):
def internal(*args, **kwargs):
para = {}
para["name"] = name
para["type"] = type
json["parameters"].append = para
func(args, kwargs)
return internal
return wrapepr
Similarly, other handlers could be written. At the end, I can just call one function which would get all formed JSONs for each function.
End output could be
[
{fun_name, "get_employee", author: "Joey", parameters : [{para_name : Name, type: str}, ... ], returns: {type: Employee, desc: "..."}
{fun_name, "search_employee", author: "Bob", parameters : [{para_name : age, type: int}, ... ], returns: {type: Employee, desc: "..."}
...
}
]
I'm not sure how I can maintain the state and know to consolidate the data regarding one function should be handled together.
How can I achieve this?
I don't know if I fully get your use case, but wouldn't it work to add author to your current functions as:
func_list = []
def func(var):
return var
json = {}
json['author'] = 'JohanL'
json['func'] = func.func_name
func.json = json
func_list.append(func.json)
def func2(var):
return var
json = {}
json['author'] = 'Ganesh'
func2.json = json
func_list.append(func2.json)
This can be automated using a decorator as follows:
def author(author):
json = {}
def author_decorator(func):
json['func'] = func.func_name
json['author'] = author
func.json = json
return func
return author_decorator
def append(func_list):
def append_decorator(func):
func_list.append(func.json)
return func
return append_decorator
func_list = []
#append(func_list)
#author('JohanL')
def func(var):
return var
#append(func_list)
#author('Ganesh')
def func2(var):
return var
Then you can access the json dict as func.json and func2.json or find the functions in the func_list. Note that for the decorators to work, you have to add them in the order I have put them and I have not added any error handling.
Also, if you prefer the func_list to not be explicitly passed, but instead use a globaly defined list with an explicit name, the code can be somewhat simplified to:
func_list = []
def author(author):
json = {}
def author_decorator(func):
json['func'] = func.func_name
json['author'] = author
func.json = json
return func
return author_decorator
def append(func):
global func_list
func_list.append(func.json)
return func
#append
#author('JohanL')
def func(var):
return var
#append
#author('Ganesh')
def func2(var):
return var
Maybe this is sufficient for you?

Python switch case

I am trying to use dictionary as switch case on python, however, the parameter does not seem to be pass to the called function, please help:
def switchcase(num,cc):
def fa(num):
out= num*1.1;
def fb(num):
out= num*2.2;
def fc(num):
out= num*3.3;
def fd(num):
out= num*4.4;
options = {
"a":fa(num),
"b":fb(num),
"c":fc(num),
"d":fd(num)
}
out=0
options[cc];
return out
print switchcase(10,"a")
the output is 0, I could not figure out the problem
The problem is:
out=0
options[cc];
return out
Basically -- no matter what options[cc] gives you, you're going to return 0 because that's the value of out. Note that setting out in the various fa, fb, ... functions does not change the value of out in the caller.
You probably want:
def switchcase(num,cc):
def fa(num):
return num*1.1;
def fb(num):
return num*2.2;
def fc(num):
return num*3.3;
def fd(num):
return num*4.4;
options = {
"a":fa(num),
"b":fb(num),
"c":fc(num),
"d":fd(num)
}
return options[cc];
Also note that this will be horribly inefficient in practice. You're creating 4 functions (and calling each) every time you call switchcase.
I'm guessing that you actually want to create a pre-made map of functions. Then you can pick up the function that you actually want from the map and call it with the given number:
def fa(num):
return num*1.1
def fb(num):
return num*2.2
def fc(num):
return num*3.3
def fd(num):
return num*4.4
OPTIONS = {
"a":fa,
"b":fb,
"c":fc,
"d":fd
}
def switchcase(num,cc):
return OPTIONS[cc](num)
Here is an alternative take. You can just navigate to the necessary methods you have outside the switcher, and also pass optional arguments if you need:
def fa(num):
return num*1.1
def fb(num):
return num*2.2
def fc(num):
return num*3.3
def fd(num, option=1):
return num*4.4*option
def f_default(num):
return num
def switchcase(cc):
return {
"a":fa,
"b":fb,
"c":fc,
"d":fd,
}.get(cc, f_default)
print switchcase("a")(10) # for Python 3 --> print(switchcase("a")(10))
print switchcase("d")(10, 3) # for Python 3 --> print(switchcase("d")(10, 3))
print(switchcase("a")(10))
11.0
print(switchcase("d")(10, 3))
132.0
print(switchcase("ddd")(10))
10
Another shorter version would be:
def switchcase(num, cc):
return {
"a": lambda: num * 1.1,
"b": lambda: num * 2.2,
"c": lambda: num * 3.3,
"d": lambda: num * 4.4,
}.get(cc, lambda: None)()
print (switchcase(10,"a"))

Is it possible to do "extended" time monitoring in Python using a decorator?

I have a simple set of functions that use each other. For example:
def func(x)
y = func_1(x)
z = func_2(y)
return z
def func_1(x):
return x + 1
def func_2(x)
a = func_a(x)
b = func_b(y)
return b
As you can see, the func is the "root" function that uses func_1 and func_2 and func_2, in its turn, uses func_a and func_b. When I call func I get z as the result.
Now I would like to "modify" or "extend" my functions with a decorator such that in the end (as a result of func) I get not only z but also an object that shows me how much it took to execute this function as well as what functions have been used by the function and how long it took to execute these "sub-functions" as well as what "sub-sub-functions" have been used by what "sub-functions" and how long does it took to execute them. To make it simpler I give an example of what I expect as an "additional" result:
{
'fname' : 'func',
'etime' : 12.000,
'subs' : [
{
'fname' : 'func_1',
'etime' : 2.000,
'subs' : []
},
{
'fname' : 'func_2',
'etime' : 10,
'subs' : [
{
'fname' : 'func_a',
'etime' : 6,
'subs' : []
},
{
'fname' : 'func_b',
'etime' : 4
'subs' : []
}
]
}
]
}
In the above example "fname" means name of the function, "etime" means execution time (how long did it took to execute this function), and "subs" is a list of sub-function that were used by the considered function. For each sub-function we have the same keys ("fname", "etime", "subs"). So, it is a "recursive" structure. If a function did not use any function then "subs" maps to an empty list.
I have started with the following decorator:
def decorate(func):
def wrapper(*args, **kw):
d = {}
d['fname'] = func.__name__
t0 = time.time()
out = func(*args, **kw)
d['etime'] = time.time() - t0
d['subs'] = ?
?.append(d)
return wrapper
But then I stack with the further implementation. I cannot find a solution and am not even sure that it is possible.
The idea is that I use a decorator to extend the number of arguments passed to each function. Each function gets an empty list containing all sub-functions used so far and append itself to this list.
You would be better using a real profiler as suggested.
Still, it can be done with a decorator class. You'll be able to keep track of the subs list with a stack shared between all the decorator's instances.
class profile(object):
#class variable used as a stack of subs list
stack = [[]]
def __init__(self, f):
self.f = f
def __call__(self, *args, **kw):
func = dict(fname = self.f.__name__)
#append the current function in the latest pushed subs list
profile.stack[-1].append(func)
#push a new subs list in the stack
profile.stack.append([])
#execution time of the actual call
t0 = time.time()
out = self.f(*args, **kw)
func['etime'] = time.time() - t0
#pull the subs list from the stack
func['subs'] = profile.stack.pop()
return out
#classmethod
def show(cls):
import json #useful to prettify the ouput
for func in cls.stack[0]:
print json.dumps(func, sort_keys=True, indent=4)
You'll have to decorate all the functions you want to appear in the profile with #profile.
Note that in a real world situation, you might want to handle exceptions when a decorated function fails.
Ouput:
profile.show() shows the list of all the called 'root' functions profiled with all their inners' calls.
{
"etime": 4.5,
"fname": "func",
"subs": [
{
"etime": 1.0,
"fname": "func_1",
"subs": []
},
{
"etime": 3.5,
"fname": "func_2",
"subs": [
{
"etime": 1.5,
"fname": "func_a",
"subs": []
},
{
"etime": 2.0,
"fname": "func_b",
"subs": []
}
]
}
]
}

Categories