applying list of functions to list of arguments in python - python

I have the following lists
fncs = ["MyLinkedList","addAtHead","get","addAtTail"]
args = [[],[8],[1],[81]]
And I want to return
[MyLinkedList(), addAtHead(8), get(1), addAtTail(81)]
I thought I could use fnc_vals = [f(x) for f, x in zip(fncs, args)] but that doesn't seem to work since my fncs list is a list of strings. How can I apply a list of functions to a list of arguments (in Python)?

If you have a list of strings refering to the current scope functions you can use globals or locals:
fnc_vals = [golbals()[f](x) for f, x in zip(fncs, args)]
Check this example:
>>> def foo(x):
... return x
...
>>> globals()["foo"](10)
10
You can also build your own functions addressing dictionary:
>>> def foo(x):
... return x
...
>>> def bar(x):
... return x + 10
...
>>> func_dict = {f.__name__:f for f in (foo, bar)}
>>> func_dict["foo"](10)
10

If the functions are in the local namespace, just remove the quotes:
fncs = [MyLinkedList, addAtHead, get, addAtTail]
args = [[], [8], [1], [81]]
If the 1st list must be strings, you can get the function objects with:
function_names = ["MyLinkedList", "addAtHead", "get", "addAtTail"]
functions = [locals()[fn] for fn in function_names]
If, that is, the functions are named in the local namespace.

Related

Creating a Python Object from a String in Python 3

This is not a duplicate of creating a function object from a string because that is a Python 2 solution with exec not as a function()
Trying to implement that solution in Python 3 gets this:
d = {}
exec("def f(x): return x")in d
print(d)
returns:
{}
So the question is, how do I create a function in Python 3 from an arbitrary string? (In my case read in from a YAML file, but that's a side issue.)
X in d , returns True if X is found in element d.
Your exec call is defining function f in global scope.
This appears to do what you want it to:
>>> d = {}
>>> exec("def f(x): return x", d)
>>> d["f"]("Hello World")
'Hello World'
>>> d={}
>>> exec("def f(x): return x",None,d)
>>> d['f'](2)
2
>>>

Map function application over a list of functions without lambda in python

I have the following code:
def f1():
print("f1")
def f2():
print("f2")
flist = [f1,f2]
list(map(lambda x: x(), flist))
I need to get rid of lambda because it cannot be dumped using pickle.
Is there any function or construction that runs the function received as parameter ?
Here is the actually code I need to modify and remove the helper function "call":
from multiprocessing import Pool
def call(x):
x()
p = Pool()
p.map(call, func_list)
You could try
[f() for f in flist]
Hope this helps :)
The map function is not a desire approach for this task based on python documentation :
map Return an iterator that applies function to every item of iterable, yielding the results.
And here you are just dealing with functions and you want to call them, So you can use a list comprehension or loop over your function list and call them in anyway you like.
But if your functions return values I suggest to use list comprehension because here since you just print some text your functions return None and you will create an extra list :
>>> [func() for func in flist]
f1
f2
[None, None]
In this case a simple loop would be efficient :
>>> for func in flist:
... func()
...
f1
f2
And if your functions return values you can use a list comprehension :
>>> def f1():
... return "f1"
...
>>> def f2():
... return "f2"
...
>>> flist = [f1,f2]
>>> [func() for func in flist]
['f1', 'f2']

How might one change the syntax of python list indexing?

After asking this question, it received a comment about how you could do something like this:
>>> def a(n):
print(n)
return a
>>> b = a(3)(4)(5)
3
4
5
Is it possible to use this or similar concepts to make it possible to index lists like my_list(n) instead of my_list[n]?
You'd have to use a custom class, and give it a __call__ special method to make it callable. A subclass of list would do nicely here:
class CallableList(list):
def __call__(self, item):
return self[item]
You cannot use this to assign to an index, however, only item access works. Slicing would require you to use to create a slice() object:
a = CallableList([1, 2, 3])
a(2)
a(slice(None, 2, None))
nested = CallableList([1, 2, CallableList([4, 5, 6])])
nested(2)(-1)
For anything more, you'd have to create a custom Python syntax parser to build an AST, then compile to bytecode from there.
the parentheses in my_list() are treated as a function call. If you want, you could write your own class that wraps a list and overwrite the call method to index into the list.
class MyList(object):
def __init__(self, alist):
self._list = alist
def __call__(self, index):
return self._list[index]
>>> mylist = MyList(['a','b','c','d','e','f'])
>>> mylist(3)
'd'
>>> mylist(4)
'e'
You could create a function that returns a lambda function:
def make_callable(some_list):
return lambda x: some_list[x]
original_list = [ 1, 2, 3, 4 ]
callable_list = make_callable(original_list)
print(callable_list(1)) # Prints 2

How do you apply a list of lambda functions to a single element using an iterator?

I want to apply a list of lambda functions to a single element using an iterable that has to be created with yield.
The list of lambda functions would have something like:
[<function <lambda> at 0x1d310c8>, <function <lambda> at 0x1d355f0>]
And I want to apply every function, from left to right , to a single element using yield to construct an iterable to iterate the list
def apply_all(functions, item):
for f in functions:
yield f(item)
Example usage:
functions = [type, id, hex]
for result in apply_all(functions, 55):
print result
gives
<type 'int'>
20326112
0x37
Give this a shot:
def lambda_apply(unnamed_funcs, element):
for unnamed in unnamed_funcs:
yield unnamed(element)
>>> l = [lambda x: x**2, lambda x: 2*x]
>>> el = 5
>>> for y in lambda_apply(l, el):
... print y
...
25
10
Note that this works not only for a list of unnamed functions, but any list of functions of arity 1. This is because all functions, named or not, are first class objects in python. You can store them in a list, and use them later, as demonstrated above.
The answer could be formulated as
import numpy as np
def apply_funcs( funcs, val ):
for func in funcs:
yield func(val)
my_funcs = [lambda x: np.cos(x), np.sin, np.tan]
my_val = 0.1
for res in apply_funcs( my_funcs, my_val ):
print res
where the apply_funcs function does the trick and the rest is just for demonstration purposes.
Do you necessarily need a yield statement?
Because there is another way to create generator: to use ().
applied_it = (f(item) for f in functions)
def apply(value, lambda_list):
for function in lambda_list:
yield (function(value))

How simple list functions could be implemented in Python

I know that Python has built-in list functions but I'm curious as to how one would write a function to sum a list and a function to reverse a list. I was able to figure out how to write some other list functions (sort, count, index, etc.) but not these, and I imagine some other languages don't have these built-in functions.
Could someone show me some Python code for those 2 functions, not using any other built-in functions?
For summing a list, you can do:
sum([1, 2, 3, 4])
And for reversing a list, this will return a new, reversed list by using Python's slices:
[1, 2, 3, 4][::-1]
Now if you don't want to use built-in functions:
def sum(lst):
s = 0
for e in lst:
s += e
return s
def reverse(lst):
l = []
for e in lst:
l = [e] + l
return l
Sum a list
Straight from the Python manual:
>>> def sum(seq):
... def add(x,y): return x+y
... return reduce(add, seq, 0)
>>> sum(range(1, 11))
55
>>> sum([])
0
This could be done as a one-liner (...ish) using lambda (Python's anonymous function syntax):
def sum(seq):
return reduce(lambda x, y: x + y, seq, 0)
Don't want to use reduce?
def sum(seq):
total = 0
for s in seq:
total += s
return total

Categories