Dictionary mapping multiple functions to key - Python - python

I understand we can use dictionary mapping with functions like this:
def call_functions(input)
def function1():
print "called function 1"
def function2():
print "called function 2"
def function3():
print "called function 3"
tokenDict = {"cat":function1,
"dog":function2,
"bear":function3}
return tokenDict[input]()
But what if we want to set two functions as a value in the dictionary? Like:
tokenDict = {"cat":function1, function2
"dog":function2
....
I tried using a list like "cat":[function1, function2] but is there an easier way to do it?
When I call it, I want it to execute function1 and then function2

As per Tyler's comment, use lists throughout for consistency. Then use a list comprehension to output the result of applying each function in your list.
Here's a working example:
def call_functions(i, val=3):
def function1(x):
return x*1
def function2(x):
return x*2
def function3(x):
return x*3
tokenDict = {"cat": [function1, function2],
"dog": [function2],
"bear": [function3]}
return [f(val) for f in tokenDict[i]]
call_functions('cat') # [3, 6]
call_functions('dog') # [6]
call_functions('bear') # [9]
Side note: you should not shadow the built-in input.

What do you mean "assign two functions to a key"? For that matter, what do you mean with assigning two anythings to a dictionary key? You need to bundle them together somehow, because the entire point of a dictionary is that each key corresponds to exactly one value (if that value is a bundle, so be it). The other answer covers that.
If you want both of those functions to be executed, and you're not going to be changing this approach much in the immediate future, you could also use a wrapper function that simply calls them in sequence:
def function4:
function1()
function2()

Related

Python distinguish between returned tuple and multiple values

I want to write a wrapper function which call one function and pass the results to another function. The arguments and return types of the functions are the same, but I have problem with returning lists and multiple values.
def foo():
return 1,2
def bar():
return (1,2)
def foo2(a,b):
print(a,b)
def bar2(p):
a,b=p
print(a,b)
def wrapper(func,func2):
a=func()
func2(a)
wrapper(bar,bar2)
wrapper(foo,foo2)
I am searching for a syntax which works with both function pairs to use it in my wrapper code.
EDIT: The definitions of at least foo2 and bar2 should stay this way. Assume that they are from an external library.
There is no distinction. return 1,2 returns a tuple. Parentheses do not define a tuple; the comma does. foo and bar are identical.
As I overlooked until JacobIRR's comment, your problem is that you need to pass an actual tuple, not the unpacked values from a tuple, to bar2:
a = foo()
foo2(*a)
a = bar()
bar2(a)
I don't necessarily agree with the design, but following your requirements in the comments (the function definitions can't change), you can write a wrapper that tries to execute each version (packed vs. unpacked) since it sounds like you might not know what the function expects. The wrapper written below, argfixer, does exactly that.
def argfixer(func):
def wrapper(arg):
try:
return func(arg)
except TypeError:
return func(*arg)
return wrapper
def foo():
return 1,2
def bar():
return (1,2)
#argfixer
def foo2(a,b):
print(a,b)
#argfixer
def bar2(p):
a,b=p
print(a,b)
a = foo()
b = bar()
foo2(a)
foo2(b)
bar2(a)
bar2(b)
However, if you aren't able to put the #argfixer on the line before the function definitions, you could alternatively wrap them like this in your own script before calling them:
foo2 = argfixer(foo2)
bar2 = argfixer(bar2)
And as mentioned in previous comments/answers, return 1,2 and return (1,2) are equivalent and both return a single tuple.
This code does not run because of arg differences. It runs if you use def foo2(*args): and def bar2(*p):.
The return 1, 2 and return (1, 2) are equivalent. The comma operator just creates a tuple, whether it is enclosed in parentheses or not.
All programming languages that I know of return a single value, so, since you want to return multiple, those values must be wrapped into a collection type, in this case, a tuple.
The problem is in the way you call the second function. Make it bar2(a) instead of bar2(*a), which breaks the tuple into separate arguments.

How to create a function that takes dictionary inputs?

I am using a module for a project, I have to pass a function to the module and the model does something like:
class module:
def __init__(self, function, dictionary):
# dictionary is {'x':2, 'y':4, 'z':23}
function(**dictionary)
And my function is something like:
def function(*foo):
return sum(foo)
The problem is that, the module needs named variables, and will pass it to the function like an unpacked dictionary, and the number of elements in dictionary can be variable, so I cannot pre-write the function as def function(x,y,z): return sum(x,y,z), and this raises an error. I do not wish to modify the module, because then, the code will not be universal. How can I solve this problem by just changing my code?
EDIT: I need foo as a list to use in the function
You module that you can't change is calling your function with:
function(**dictionary)
You won't be able to write your function to the argument is a list — it's not being passed a list. You can accept the keywords as a dict and the easily make a list. Your function just needs to be prepared to be called that way:
def f(**foo):
This leads to:
class module:
def __init__(self, function, dictionary):
# dictionary is {'x':2, 'y':4, 'z':23}
function(**dictionary)
def f(**foo):
print(sum(foo.values()))
module(f, {'x':2, 'y':4, 'z':23})
# prints 29 as expected
def function(*args,**Kwargs):
try:
return sum(*args)
else:
return sum(**kwargs.values())
double * unpacked dictionary values, and one * is to unpacked anything(except dictionary).
The number and type of arguments are determined by code of function init
In your case this a single argument of type dictionary. So you have always to pass such function f(x) where x is a dictionary.
So the that is function f that deals with the argument.
E.g.
def fsum(x): return sum(x.values())
...
__init__(fsum, {'a': 1, 'b': 2, 'c': 3})
It seems you want the sum of the values:
def __init__(self, function, dictionary):
# dictionary is {'x':2, 'y':4, 'z':23}
function(dictionary.values())
The dictionary.values() will give a list of [2, 4, 23] for your example.

Getting inputs to a function from a python object

I have a class. This class has a list of functions that are to be evaluated by a different program.
class SomeClass(object):
def __init__(self, context):
self.functions_to_evaluate = []
There is a function that adds functions to an instance of SomeClass, via something like:
new_function = check_number(5)
SomeClassInstance.functions_to_evaluate.append(new_function)
Where check_number is a function that will check if number is greater than 10, let's say.
If I take SomeClassInstance.functions_to_evaluate and print it, I get a bunch of python objects, like so:
<some_library.check_number object at 0x07B35B90>
I am wondering if it is possible for me to extract the input given to check_number, so something like:
SomeClassInstance.functions_to_evaluate[0].python_feature() that will return "5" or whatever the input to check_number was to me.
You can use the standard library functools.partial, which creates a new partially applied function *.
>>> from functools import partial
>>> def check_number(input):
... return input > 10
>>> fn = partial(check_number, 5)
>>> fn.args # this attribute gives you back the bound arguments, as a tuple.
(5,)
>>> fn() # calls the function with the bound arguments.
False
*: actually the partial object is not a function instance, but it is a callable, and from a duck-type perspective it's a function.
If new_function = check_number(5) is a closure, then you can extract this value using __closure__[0].cell_contents:
Example:
def foo(x):
def inn(y):
return x
return inn
s = foo(5)
print(s.__closure__[0].cell_contents)
Output:
5
I understand your confusion, but:
new_function = check_number(5)
Is calling the function, and the new_function variable gets assigned the return value of the function.
If you have this check_number function:
def check_number(input):
return input > 10
Then it will return False, and new_function will be False. Never <some_library.check_number object at 0x07B35B90>.
If you're getting <some_library.check_number object at 0x07B35B90> then your check_number() function is returning something else.
There are probably several ways to skin this cat. But I'd observe first and foremost that you're not adding python function objects to the functions_to_evaluate list, you're adding the evaluations of functions.
You could simply add a tuple of function, args to the list:
SomeClassInstace.functions_to_evaluate.append((check_number, 5))
And then you can:
for f, args in SomeClassInstance.functions_to_evaluate:
print(args)

Input of a function contains output of another function

A bit of a general question that I cannot find the solution for,
I currently have two functions
def func1(*args, **kwargs):
...
return a,b
and
def func2(x,y):
...
return variables
I would like my code to evaluate
variables = func2(func1())
Which python does not accept as it says func2 requires two arguments when only one is given. My current solution is doing an intermediate dummy redefinition but makes my code extremely cluttered (my "func1" has an output of many parameters).
Is there an elegant solution to this?
def func1():
return 10, 20
def func2(x, y):
return x + y
results = func2(*func1())
print results
--output:--
30
A function can only return one thing, so func1() actually returns the tuple (10, 20). In order to get two things, you need to explode the tuple with *.

Python - multiple functions - output of one to the next

I know this is super basic and I have been searching everywhere but I am still very confused by everything I'm seeing and am not sure the best way to do this and am having a hard time wrapping my head around it.
I have a script where I have multiple functions. I would like the first function to pass it's output to the second, then the second pass it's output to the third, etc. Each does it's own step in an overall process to the starting dataset.
For example, very simplified with bad names but this is to just get the basic structure:
#!/usr/bin/python
# script called process.py
import sys
infile = sys.argv[1]
def function_one():
do things
return function_one_output
def function_two():
take output from function_one, and do more things
return function_two_output
def function_three():
take output from function_two, do more things
return/print function_three_output
I want this to run as one script and print the output/write to new file or whatever which I know how to do. Just am unclear on how to pass the intermediate outputs of each function to the next etc.
infile -> function_one -> (intermediate1) -> function_two -> (intermediate2) -> function_three -> final result/outfile
I know I need to use return, but I am unsure how to call this at the end to get my final output
Individually?
function_one(infile)
function_two()
function_three()
or within each other?
function_three(function_two(function_one(infile)))
or within the actual function?
def function_one():
do things
return function_one_output
def function_two():
input_for_this_function = function_one()
# etc etc etc
Thank you friends, I am over complicating this and need a very simple way to understand it.
You could define a data streaming helper function
from functools import reduce
def flow(seed, *funcs):
return reduce(lambda arg, func: func(arg), funcs, seed)
flow(infile, function_one, function_two, function_three)
#for example
flow('HELLO', str.lower, str.capitalize, str.swapcase)
#returns 'hELLO'
edit
I would now suggest that a more "pythonic" way to implement the flow function above is:
def flow(seed, *funcs):
for func in funcs:
seed = func(seed)
return seed;
As ZdaR mentioned, you can run each function and store the result in a variable then pass it to the next function.
def function_one(file):
do things on file
return function_one_output
def function_two(myData):
doThings on myData
return function_two_output
def function_three(moreData):
doMoreThings on moreData
return/print function_three_output
def Main():
firstData = function_one(infile)
secondData = function_two(firstData)
function_three(secondData)
This is assuming your function_three would write to a file or doesn't need to return anything. Another method, if these three functions will always run together, is to call them inside function_three. For example...
def function_three(file):
firstStep = function_one(file)
secondStep = function_two(firstStep)
doThings on secondStep
return/print to file
Then all you have to do is call function_three in your main and pass it the file.
For safety, readability and debugging ease, I would temporarily store the results of each function.
def function_one():
do things
return function_one_output
def function_two(function_one_output):
take function_one_output and do more things
return function_two_output
def function_three(function_two_output):
take function_two_output and do more things
return/print function_three_output
result_one = function_one()
result_two = function_two(result_one)
result_three = function_three(result_two)
The added benefit here is that you can then check that each function is correct. If the end result isn't what you expected, just print the results you're getting or perform some other check to verify them. (also if you're running on the interpreter they will stay in namespace after the script ends for you to interactively test them)
result_one = function_one()
print result_one
result_two = function_two(result_one)
print result_two
result_three = function_three(result_two)
print result_three
Note: I used multiple result variables, but as PM 2Ring notes in a comment you could just reuse the name result over and over. That'd be particularly helpful if the results would be large variables.
It's always better (for readability, testability and maintainability) to keep your function as decoupled as possible, and to write them so the output only depends on the input whenever possible.
So in your case, the best way is to write each function independently, ie:
def function_one(arg):
do_something()
return function_one_result
def function_two(arg):
do_something_else()
return function_two_result
def function_three(arg):
do_yet_something_else()
return function_three_result
Once you're there, you can of course directly chain the calls:
result = function_three(function_two(function_one(arg)))
but you can also use intermediate variables and try/except blocks if needed for logging / debugging / error handling etc:
r1 = function_one(arg)
logger.debug("function_one returned %s", r1)
try:
r2 = function_two(r1)
except SomePossibleExceptio as e:
logger.exception("function_two raised %s for %s", e, r1)
# either return, re-reraise, ask the user what to do etc
return 42 # when in doubt, always return 42 !
else:
r3 = function_three(r2)
print "Yay ! result is %s" % r3
As an extra bonus, you can now reuse these three functions anywhere, each on it's own and in any order.
NB : of course there ARE cases where it just makes sense to call a function from another function... Like, if you end up writing:
result = function_three(function_two(function_one(arg)))
everywhere in your code AND it's not an accidental repetition, it might be time to wrap the whole in a single function:
def call_them_all(arg):
return function_three(function_two(function_one(arg)))
Note that in this case it might be better to decompose the calls, as you'll find out when you'll have to debug it...
I'd do it this way:
def function_one(x):
# do things
output = x ** 1
return output
def function_two(x):
output = x ** 2
return output
def function_three(x):
output = x ** 3
return output
Note that I have modified the functions to accept a single argument, x, and added a basic operation to each.
This has the advantage that each function is independent of the others (loosely coupled) which allows them to be reused in other ways. In the example above, function_two() returns the square of its argument, and function_three() the cube of its argument. Each can be called independently from elsewhere in your code, without being entangled in some hardcoded call chain such as you would have if called one function from another.
You can still call them like this:
>>> x = function_one(3)
>>> x
3
>>> x = function_two(x)
>>> x
9
>>> x = function_three(x)
>>> x
729
which lends itself to error checking, as others have pointed out.
Or like this:
>>> function_three(function_two(function_one(2)))
64
if you are sure that it's safe to do so.
And if you ever wanted to calculate the square or cube of a number, you can call function_two() or function_three() directly (but, of course, you would name the functions appropriately).
With d6tflow you can easily chain together complex data flows and execute them. You can quickly load input and output data for each task. It makes your workflow very clear and intuitive.
import d6tlflow
class Function_one(d6tflow.tasks.TaskCache):
function_one_output = do_things()
self.save(function_one_output) # instead of return
#d6tflow.requires(Function_one)
def Function_two(d6tflow.tasks.TaskCache):
output_from_function_one = self.inputLoad() # load function input
function_two_output = do_more_things()
self.save(function_two_output)
#d6tflow.requires(Function_two)
def Function_three():
output_from_function_two = self.inputLoad()
function_three_output = do_more_things()
self.save(function_three_output)
d6tflow.run(Function_three()) # executes all functions
function_one_output = Function_one().outputLoad() # get function output
function_three_output = Function_three().outputLoad()
It has many more useful features like parameter management, persistence, intelligent workflow management. See https://d6tflow.readthedocs.io/en/latest/
This way function_three(function_two(function_one(infile))) would be the best, you do not need global variables and each function is completely independent of the other.
Edited to add:
I would also say that function3 should not print anything, if you want to print the results returned use:
print function_three(function_two(function_one(infile)))
or something like:
output = function_three(function_two(function_one(infile)))
print output
Use parameters to pass the values:
def function1():
foo = do_stuff()
return function2(foo)
def function2(foo):
bar = do_more_stuff(foo)
return function3(bar)
def function3(bar):
baz = do_even_more_stuff(bar)
return baz
def main():
thing = function1()
print thing

Categories