I'm trying to accomplish something in Python2.5
So I have my function
def f(a,b,c,d,e):
pass
and now I'd like to call that function: (in python2.7 I would do)
my_tuple = (1,2,3)
f(0, *my_tuple, e=4)
But there is no way to do it in python2.5. I'm thinking about apply()
apply(f, something magical here)
#this doesn't work - multiple value for 'a'. But it's the only thing I came up with
apply(f, my_tuple, {"a":0, "e":4})
How would you do it? I'd like to do it inline, without putting things in list before.
If you're willing to swap the order of arguments then you could use something like this:
>>> def f(a,b,c,d,e):
... print a,b,c,d,e
...
>>> my_tuple = (1,2,3)
>>> def apply(f, mid, *args, **kwargs):
... return f(*args+mid, **kwargs)
...
>>> apply(f, my_tuple, 0, e=4)
0 1 2 3 4
>>>
>>> apply(f, ('a', 'b'), '_', d='c', e='d')
_ a b c d
>>>
Related
I am testing a function. I would like to know what are the results respect to various parameters.
If the function has only one parameter then it is easy:
def func_a(a):
return a+1
def test_func(func,parameter_list):
return {t:func(t) for t in parameter_list}
print (test_func(func_a,[2,4,5]))
prints
{2: 3, 4: 5, 5: 6}
Here instead I do it with two parameters:
def strategy_2(a,b):
return a+b
def test_2_strategies(strategy,list_of_lists):
result={}
for l1 in list_of_lists[0]:
for l2 in list_of_lists[1]:
result[(l1,l2)]=strategy_2(l1,l2)
return result
print (test_2_strategies(strategy_2,[[1,2,3],[0.3,0.6]]))
and the result is:
{(1, 0.3): 1.3, (1, 0.6): 1.6, (2, 0.3): 2.3, (2, 0.6): 2.6, (3, 0.3):
3.3, (3, 0.6): 3.6}
Perfect.
But what if I wanted to make a similar function where the list of lists could have n lists inside. And test all the combinations.
I looked at decorators, lambda, functools.partial, but I seem to be unable to do it.
I tried for example this:
def func_b(a,b):
return a+b
def test_func(func,parameter_list):
return {t:func(t) for t in parameter_list}
def test_strategy_many_parameters(func,parameter_lists):
if len (parameter_lists)>1:
test_strategy_many_parameters(test_func(lambda x: func(x,y),parameter_lists[0]), parameter_lists[1:])
else:
return test_func(func,parameter_lists[0])
but it does not work.
I am now looking at this question:
Passing functions with arguments to another function in Python?
but I fail to see how to apply it in this case.
I would like something like this:
def func(x1,x2,...,xn):
result=...
return result
def test_func(func,list_of_lists):
...
print(test_func(func,[[x1min,...,x1max],[x2min,...,x2max],...,[xnmin,...,xnmax]])
and the result would be:
{(x1min, x2min,...,xnmin):func(x1min, x2min,...,xnmin) , ,(x1max,
x2max,...,xnmax):func(x1max, x2max,...,xnmax)}
What's an elegant way to do it (or just a way to do it).
Thanks.
Take a look at itertools.product to generate arguments, and then simply call the function:
arguments = itertools.product(list_of_values_for_arg_1, list_of_values_for_arg_2, ..., list_of_values_for_arg_n)
# or
arguments = itertools.product(*list_of_lists)
for arg in arguments:
result=func(*arg)
So to generate dict you need to do something like this:
{arg: func(*arg) for arg in itertools.product(*list_of_lists)}
No need for a list of lists, just use a list of tuples (tuples as the function arguments) and it becomes as easy as your base case.
def func(a,b,c):
result=...
return result
my_tuple = (1,2,3)
func(*my_tuple)
If l is your nested list, then map(func, *l) will contain the list of all o/p from the function func with required args and {e:func(*e) for e in zip(*l)} will contain the results in dict format
>>> def func(*args):
>>> return f'O/P of func: {args}'
>>>
>>> l = [['x1min','x1max'],['x2min','x2max'],['xnmin','xnmax']]
>>> [*map(func, *l)]
["O/P of func: ('x1min', 'x2min', 'xnmin')", "O/P of func: ('x1max', 'x2max', 'xnmax')"]
>>>
>>> {e:func(*e) for e in zip(*l)}
{('x1min', 'x2min', 'xnmin'): "O/P of func: ('x1min', 'x2min', 'xnmin')", ('x1max', 'x2max', 'xnmax'): "O/P of func: ('x1max', 'x2max', 'xnmax')"}
>>>
The list.index(x) function returns the index in the list of the first item whose value is x.
Is there a function, list_func_index(), similar to the index() function that has a function, f(), as a parameter. The function, f() is run on every element, e, of the list until f(e) returns True. Then list_func_index() returns the index of e.
Codewise:
>>> def list_func_index(lst, func):
for i in range(len(lst)):
if func(lst[i]):
return i
raise ValueError('no element making func True')
>>> l = [8,10,4,5,7]
>>> def is_odd(x): return x % 2 != 0
>>> list_func_index(l,is_odd)
3
Is there a more elegant solution? (and a better name for the function)
You could do that in a one-liner using generators:
next(i for i,v in enumerate(l) if is_odd(v))
The nice thing about generators is that they only compute up to the requested amount. So requesting the first two indices is (almost) just as easy:
y = (i for i,v in enumerate(l) if is_odd(v))
x1 = next(y)
x2 = next(y)
Though, expect a StopIteration exception after the last index (that is how generators work). This is also convenient in your "take-first" approach, to know that no such value was found --- the list.index() function would throw ValueError here.
One possibility is the built-in enumerate function:
def index_of_first(lst, pred):
for i,v in enumerate(lst):
if pred(v):
return i
return None
It's typical to refer a function like the one you describe as a "predicate"; it returns true or false for some question. That's why I call it pred in my example.
I also think it would be better form to return None, since that's the real answer to the question. The caller can choose to explode on None, if required.
#Paul's accepted answer is best, but here's a little lateral-thinking variant, mostly for amusement and instruction purposes...:
>>> class X(object):
... def __init__(self, pred): self.pred = pred
... def __eq__(self, other): return self.pred(other)
...
>>> l = [8,10,4,5,7]
>>> def is_odd(x): return x % 2 != 0
...
>>> l.index(X(is_odd))
3
essentially, X's purpose is to change the meaning of "equality" from the normal one to "satisfies this predicate", thereby allowing the use of predicates in all kinds of situations that are defined as checking for equality -- for example, it would also let you code, instead of if any(is_odd(x) for x in l):, the shorter if X(is_odd) in l:, and so forth.
Worth using? Not when a more explicit approach like that taken by #Paul is just as handy (especially when changed to use the new, shiny built-in next function rather than the older, less appropriate .next method, as I suggest in a comment to that answer), but there are other situations where it (or other variants of the idea "tweak the meaning of equality", and maybe other comparators and/or hashing) may be appropriate. Mostly, worth knowing about the idea, to avoid having to invent it from scratch one day;-).
Not one single function, but you can do it pretty easily:
>>> test = lambda c: c == 'x'
>>> data = ['a', 'b', 'c', 'x', 'y', 'z', 'x']
>>> map(test, data).index(True)
3
>>>
If you don't want to evaluate the entire list at once you can use itertools, but it's not as pretty:
>>> from itertools import imap, ifilter
>>> from operator import itemgetter
>>> test = lambda c: c == 'x'
>>> data = ['a', 'b', 'c', 'x', 'y', 'z']
>>> ifilter(itemgetter(1), enumerate(imap(test, data))).next()[0]
3
>>>
Just using a generator expression is probably more readable than itertools though.
Note in Python3, map and filter return lazy iterators and you can just use:
from operator import itemgetter
test = lambda c: c == 'x'
data = ['a', 'b', 'c', 'x', 'y', 'z']
next(filter(itemgetter(1), enumerate(map(test, data))))[0] # 3
A variation on Alex's answer. This avoids having to type X every time you want to use is_odd or whichever predicate
>>> class X(object):
... def __init__(self, pred): self.pred = pred
... def __eq__(self, other): return self.pred(other)
...
>>> L = [8,10,4,5,7]
>>> is_odd = X(lambda x: x%2 != 0)
>>> L.index(is_odd)
3
>>> less_than_six = X(lambda x: x<6)
>>> L.index(less_than_six)
2
you could do this with a list-comprehension:
l = [8,10,4,5,7]
filterl = [a for a in l if a % 2 != 0]
Then filterl will return all members of the list fulfilling the expression a % 2 != 0. I would say a more elegant method...
Intuitive one-liner solution:
i = list(map(lambda value: value > 0, data)).index(True)
Explanation:
we use map function to create a list containing True or False based on if each element in our list pass the condition in the lambda or not.
then we convert the map output to list
then using the index function, we get the index of the first true which is the same index of the first value passing the condition.
I'd like to pass a tuple (or maybe a list) to a function as a sequence of values (arguments). The tuple should be then unpacked as an argument into *arg.
For example, this is clear:
def func(*args):
for i in args:
print "i = ", i
func('a', 'b', 3, 'something')
But what I want to do is this:
tup = ('a1', 'a2', 4, 'something-else')
func(tup)
And this should behave similar to the first case.
I think I should use here reprint and eval but not sure how exactly.
I know that I can just pass the tuple in the function and then unpack it within the body, but my question here is how to unpack it in the function call itself.
You can just use func(*tup) to unpack the tuple directly when you invoke the function.
>>> func(*tup)
i = a1
i = a2
i = 4
i = something-else
This is kind of equivalent to func(tup[0], tup[1], tup[2], ...). The same also works if the function expects multiple individual parameters:
>>> def func2(a, b, c, d):
... print(a, b, c, d)
...
>>> func2(*tup)
('a1', 'a2', 4, 'something-else')
See e.g. here for more in-depth background on the syntax.
You can unpack the tuple during the call by putting a * before the identifier of the tuple. This allows you to easily differentiate between tuples that should be unpacked and ones which shouldn't. This is an example:
>>> MyTuple = ('one', 2, [3])
>>>
>>> def func(*args):
... for arg in args:
... print(arg)
...
>>>
>>> func(*MyTuple)
one
2
[3]
>>>
>>> func(MyTuple)
('one', 2, [3])
You can use *args if you want to unpack your tuple.
Your method definition goes as follows :
def func(*tup):
for i in tup:
print(print "i = ",i)
Now calling your method:
tup = ('a1','a1',4,'something-else')
func(*tup)
Which will yield you the output as-
i = a1
i = a2
i = 4
i = something-else
When we use def, we can use **kwargs and *args to define dynamic inputs to the function
Is there anything similar for the return tuples, I've been looking for something that behaves like this:
def foo(data):
return 2,1
a,b=foo(5)
a=2
b=1
a=foo(5)
a=2
However if I only declare one value to unpack, it sends the whole tuple over there:
a=foo(5)
a=(2,1)
I could use 'if' statements, but I was wondering if there was something less cumbersome. I could also use some hold variable to store that value, but my return value might be kind of large to have just some place holder for that.
Thanks
If you need to fully generalize the return value, you could do something like this:
def function_that_could_return_anything(data):
# do stuff
return_args = ['list', 'of', 'return', 'values']
return_kwargs = {'dict': 0, 'of': 1, 'return': 2, 'values': 3}
return return_args, return_kwargs
a, b = function_that_could_return_anything(...)
for thing in a:
# do stuff
for item in b.items():
# do stuff
In my opinion it would be simpler to just return a dictionary, then access parameters with get():
dict_return_value = foo()
a = dict_return_value.get('key containing a', None)
if a:
# do stuff with a
I couldn't quite understand exactly what you're asking, so I'll take a couple guesses.
If you want to use a single value sometimes, consider a namedtuple:
from collections import namedtuple
AAndB = namedtuple('AAndB', 'a b')
def foo(data):
return AAndB(2,1)
# Unpacking all items.
a,b=foo(5)
# Using a single value.
foo(5).a
Or, if you're using Python 3.x, there's extended iterable unpacking to easily unpack only some of the values:
def foo(data):
return 3,2,1
a, *remainder = foo(5) # a==3, remainder==[2,1]
a, *remainder, c = foo(5) # a==3, remainder==[2], c==1
a, b, c, *remainder = foo(5) # a==3, b==2, c==1, remainder==[]
Sometimes the name _ is used to indicate that you are discarding the value:
a, *_ = foo(5)
This question already has answers here:
How to get method parameter names?
(20 answers)
Closed last month.
Is there an easy way to be inside a python function and get a list of the parameter names?
For example:
def func(a,b,c):
print magic_that_does_what_I_want()
>>> func()
['a','b','c']
Thanks
Well we don't actually need inspect here.
>>> func = lambda x, y: (x, y)
>>>
>>> func.__code__.co_argcount
2
>>> func.__code__.co_varnames
('x', 'y')
>>>
>>> def func2(x,y=3):
... print(func2.__code__.co_varnames)
... pass # Other things
...
>>> func2(3,3)
('x', 'y')
>>>
>>> func2.__defaults__
(3,)
For Python 2.5 and older, use func_code instead of __code__, and func_defaults instead of __defaults__.
locals() returns a dictionary with local names:
def func(a, b, c):
print(locals().keys())
prints the list of parameters. If you use other local variables those will be included in this list. But you could make a copy at the beginning of your function.
If you also want the values you can use the inspect module
import inspect
def func(a, b, c):
frame = inspect.currentframe()
args, _, _, values = inspect.getargvalues(frame)
print 'function name "%s"' % inspect.getframeinfo(frame)[2]
for i in args:
print " %s = %s" % (i, values[i])
return [(i, values[i]) for i in args]
>>> func(1, 2, 3)
function name "func"
a = 1
b = 2
c = 3
[('a', 1), ('b', 2), ('c', 3)]
import inspect
def func(a,b,c=5):
pass
inspect.getargspec(func) # inspect.signature(func) in Python 3
(['a', 'b', 'c'], None, None, (5,))