passing a tuple in *args - python

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

Related

python 3: how do I run a function over a list of lists of possible parameters and returning a dictionary of all results

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')"}
>>>

Python: Accept multiple arguments

In Python I am trying to make a function that can accept 1 or more arguments. For simplicity let's say I want to make a function that prints all the arguments that are passed
def print_all(**arguments**):
print(arg1, arg2, ..., argN)
so print_all("A", "B") would output AB.
The number of arguments passed could be 1 or more strings.
What is the best way to do this?
*args and **kwargs allow to pass any no of arguments, positional (*) and keyword (**) to the function
>>> def test(*args):
... for var in args:
... print var
...
>>>
For no of variable
>>> test("a",1,"b",2)
a
1
b
2
>>> test(1,2,3)
1
2
3
For list & dict
>>> a = [1,2,3,4,5,6]
>>> test(a)
[1, 2, 3, 4, 5, 6]
>>> b = {'a':1,'b':2,'c':3}
>>> test(b)
{'a': 1, 'c': 3, 'b': 2}
For detail
Simply this:
def print_all(*args):
for arg in args:
print(arg)
Use the splat operator (*) to pass one or more positional arguments. Then join them as strings in your function to print the result.
def print_all(*args):
print("".join(str(a) for a in args))
>>> print_all(1, 2, 3, 'a')
123a
You are looking for the usage of *args which allows you to pass multiple arguments to function without caring about the number of arguments you want to pass.
Sample example:
>>> def arg_funct(*args):
... print args
...
>>> arg_funct('A', 'B', 'C')
('A', 'B', 'C')
>>> arg_funct('A')
('A',)
Here this function is returning the tuple of parameters passed to your function.
For more details, check: What does ** (double star) and * (star) do for parameters?

Passing several arguments from an array to a function in a easy way

Well I really don't know how to describe this in words but I've an easy example:
def foo(x,y,z):
r=x+....
a = [1,2,3]
foo(a[0], a[1], a[2])
Can I do the same without calling a[n] several times? but keeping "x,y,z" definition?
Use the unpacking operator!
>>> def foo(x,y,z):
... return x+y+z
...
>>> a = [1,2,3]
>>> foo(*a)
6
From the documentation
If they are not available separately, write the function call with the
*-operator to unpack the arguments out of a list or tuple:
>>> args = [3, 6]
>>> range(*args) # call with arguments unpacked from a list [3, 4, 5]
Yeah use unpacking operator to pass any arbitrary arguments to your function :
def foo(*args):
for i in args : # you can iterate over args or get its elements by indexing
#do stuff
a = [1,2,3]
foo(*a)
And if you just pass 3 argument you can use unpacking in call time.
def foo(x,y,z):
r=x+....
a = [1,2,3]
foo(*a)
Try this
def foo(x,y,z):
r=x+....
a = [1,2,3]
foo(*a)

Is there a more pythonic way of exploding a list over a function's arguments?

def foo(a, b, c):
print a+b+c
i = [1,2,3]
Is there a way to call foo(i) without explicit indexing on i?
Trying to avoid foo(i[0], i[1], i[2])
Yes, use foo(*i):
>>> foo(*i)
6
You can also use * in function definition:
def foo(*vargs) puts all non-keyword arguments into a tuple called vargs.
and the use of **, for eg., def foo(**kargs), will put all keyword arguments into a dictionary called kargs:
>>> def foo(*vargs, **kargs):
print vargs
print kargs
>>> foo(1, 2, 3, a="A", b="B")
(1, 2, 3)
{'a': 'A', 'b': 'B'}
It's called argument unpacking and there's an operator for it.
foo(*i)
By the way, it works with any iterable, not just with lists.
Yes, Python supports that:
foo(*i)
See the documentation on Unpacking Argument Lists. Works with anything iterable. With two stars ** it works for dicts and named arguments.
def bar(a, b, c):
return a * b * c
j = {'a': 5, 'b': 3, 'c': 2}
bar(**j)

Getting list of parameter names inside python function [duplicate]

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,))

Categories

Resources