Let's say that I have a function which takes 10 arguments and another functions which takes 11 arguments and the second one is calling the first one. My code:
def func10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10):
return a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
def func11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11):
return a11 func10(a1=a1, a2=a2, a3=a3, a4=a4, a5=a5, a6=a6, a7=a7, a8=a8, a9=a9, a10=a10)
Is it possible to write it nicer, i.e. without writing a1=a1, a2=a2, ...
?
EDIT
Maybe to be more precise: in the function func11
the arguments are a1, a2, ... a11
. Ten of these arguments are also passed to func10
function with exactly the same names. I would like to make this works:
def func11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11):
return a11 func10(arguments)
func11(a1=a1, a11=11, a2=a2, a3=a3, a4=a4, a5=a5, a6=a6, a7=a7, a8=a8, a9=a9, a10=10)
so that I can change the order of arguments when calling func11
but the proper arguments (i.e. a1 - a10) should be passed to func10
inside func11
in a simple way instead of writing again a1=a1
.... How can I do that? And I don't want to do summation in my function, this is just an example!
CodePudding user response:
You don't need to explicitly state a1=a1
for every argument func10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
will do the same although you most likely should consider using *args
or **kwargs
for something like this.
Example:
def func10(*args):
total = 0
for num in args:
total = num
return num
Edit: To clarify this would only work if you intended on doing something similar with each argument
Check @MatsLindh answer I think its the best for your scenario if your doing anything more advanced than the solution I suggested (which is likely)
CodePudding user response:
Define your functions to instead take a list of arguments for a1-a10 then specify a11 as a keyword argument:
def func10(*args):
return sum(args)
def func11(*args, **kwargs):
return kwargs['a11'] func10(*args)
print(func11(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, a11=11))
# Outputs 66
Note: This assume a11
exists.
CodePudding user response:
In python you can use *args
and **kwargs
to pass arguments to a function. Here's some examples on how you could use them:
using args
only
def func10(*args):
return sum(args)
def func11(*args):
return args[-1] func10(*args[:-1])
the_args = [1,2,3,4,5,6,7,8,9,10,42]
print(func11(*the_args))
using kwargs
and ignoring a11
def func10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, **ignored_kwargs):
return a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
def func11(**kwargs):
return kwargs['a11'] func10(**kwargs)
the_kwargs = dict(a1=1, a2=2, a3=3, a4=4, a5=5, a6=6, a7=7, a8=8, a9=9, a10=10, a11=42)
print(func11(**the_kwargs))
using kwargs
values assuming order is correct as args
def func10(*args):
return sum(args[:-1])
def func11(**kwargs):
return kwargs['a11'] func10(*kwargs.values())
the_kwargs = dict(a1=1, a2=2, a3=3, a4=4, a5=5, a6=6, a7=7, a8=8, a9=9, a10=10, a11=42)
print(func11(**the_kwargs))
CodePudding user response:
You don’t need the equals sign and the extra
You can just call it like this:
def func11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11):
return a11 func10(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
As far as I know you only need argname=object when you use kwargs or a single kwarg.
Update: to match the questions update.
You can define function 11 with kwargs and then pass them on.
def func11(**kwargs):
return kwargs[‘a11’] func10(kwargs[‘a1’],kwargs[‘a2’], etc.)
#this let’s you change the position how you want ;)
CodePudding user response:
"""
The following takes advantage of un-packing in function 11.
Receive 10 arguments in func10 pass the 10 arguments to func11
in a different order plus one additional argument.
"""
def func10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10):
print('func10 original order ',[a1, a2, a3, a4, a5, a6, a7, a8, a9, a10] )
a11 = 5
# Pass original arguments to func11 in different order
for_func11 = [a3, a2, a1, a4, a6, a5, a7, a8, a11, a10,a9]
func11(*for_func11)
return a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
def func11(b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11):
print('func11 parameter values',list((b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11)))
return b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11
func10(1, 2, 3, 4, 6, 7, 8, 9, 10, 11)
output
func10 original order [1, 2, 3, 4, 6, 7, 8, 9, 10, 11]
func11 parameter values [3, 2, 1, 4, 7, 6, 8, 9, 5, 11, 10]
CodePudding user response:
def func10(data):
return sum(data)
def func11(data):
return data[10] func10(data[:10:])
def main():
a1 = 1
a2 = 2
a3 = 3
a4 = 4
a5 = 5
a6 = 6
a7 = 7
a8 = 8
a9 = 9
a10 = 10
a11 = 11
print(func11([a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11]))
Based on your edit you can change the order of the arguments inside the list for the initial func11 call.
CodePudding user response:
You can do a bit of trickery by using locals()
as the first statement inside your function, effectively capturing all the arguments given to the function and their values. You can then use **kwargs
to pass these on to the previous function - but you need to remove a11
first, since func10
doesn't know anything about it.
def func10(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10):
return a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
def func11(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11):
given_args = locals()
del given_args['a11']
return func10(**given_args) a11
print(func10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
print(func11(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11))
Output:
55
66
However, if this is something you see yourself having to do a lot, you might want to define a1
, a2
etc. as properties of a Pydantic model instead, and then let each step populate another value in that model.