Pass a List to a Function to Act as Multiple Arguments

Pass a list to a function to act as multiple arguments

function_that_needs_strings(*my_list) # works!

You can read all about it here.

Pass a list to function with variable number of args in python

Yes, just unpack the list using the same *args syntax you used when defining the function.

my_list = [1,2,3]
result = add(*my_list)

Also, be aware that args[1:] contains strings. Convert these strings to numbers first with

numbers = [float(x) for x in args[1:]]

or

numbers = map(float, args[1:]) # lazy in Python 3

before calling add with *numbers.

Short version without your add function:

result = sum(map(float, args[1:]))

Converting list to *args when calling function

You can use the * operator before an iterable to expand it within the function call. For example:

timeseries_list = [timeseries1 timeseries2 ...]
r = scikits.timeseries.lib.reportlib.Report(*timeseries_list)

(notice the * before timeseries_list)

From the python documentation:

If the syntax *expression appears in the function call, expression
must evaluate to an iterable. Elements from this iterable are treated
as if they were additional positional arguments; if there are
positional arguments x1, ..., xN, and expression evaluates to a
sequence y1, ..., yM, this is equivalent to a call with M+N positional
arguments x1, ..., xN, y1, ..., yM.

This is also covered in the python tutorial, in a section titled Unpacking argument lists, where it also shows how to do a similar thing with dictionaries for keyword arguments with the ** operator.

Python 3.x: enter one list as multiple parameters in a function

Use * operator

list = [1, 2, 3, n]
foo(*list) # Function with n arguments

For example:

def foo(one, two):
print(one, two)


list_1 = [1, 2]
list_2 = [1, ]

# Call with list_* variable
foo(*list_1) # Print 1, 2
foo(*list_2) # TypeError, but requiere more arguments.

For solve TypeError, can use *args for has dynamic arguments in your function

How to pass multiple arguments including arrays to a function in Bash where order is not defined and array elements can have multiple words?

How can I solve the second example, where the order or parameter can vary?

There are two universal independent of programming language solutions to join a variadic length of a list of items together that any programmers should know about:

  1. Pass the count...

my_func() {
local tmp optionsa title text optionsb
tmp=$1
shift
while ((tmp--)); do
optionsa+=("$1")
shift
done
title="$1"
shift
tmp=$1
shift
while ((tmp--)); do
optionsb+=("$1")
shift
done
text=$1
my_command "${optionsa[@]}" "$title" "${optionsb[@]}" "$text"
}

my_func 0 "Title" 0 "Text"
my_func 0 "Title" "${#optionsb[@]}" "${optionsb[@]}" "Text"
my_func "${#optionsa[@]}" "${optionsa[@]}" "Title" "${#optionsb[@]}" "${optionsb[@]}" "Text"

  1. Use a sentinel value.

my_func() {
local tmp optionsa title text optionsb
while [[ -n "$1" ]]; do
optionsa+=("$1")
shift
done
title=$1
shift
while [[ -n "$1" ]]; do
optionsb+=("$1")
shift
done
text=$1
my_command "${optionsa[@]}" "$title" "${optionsb[@]}" "$text"
}
my_func "" "Title" "" "Text"
my_func "" "Title" "${optionsb[@]}" "" "Text"
my_func "${optionsa[@]}" "" "Title" "${optionsb[@]}" "" "Text"

And I see two bash specific solutions:


  1. Pass arrays as names and use namereferences.

my_func() {
# Use unique names to avoid nameclashes
declare -n _my_func_optionsa=$1
local title=$2
declare -n _my_func_optionsb=$3
local title=$4
my_command "${_my_func_optionsa[@]}" "$title" "${_my_func_optionsb[@]}" "$text"
}

# arrays have to exists
my_func optionsa "Title" optionsb "Text"

  1. Parse the arguments like a real man. This is actually universal solution, as it generally performs data serialization when creating list of arguments and then data deserialization when reading the arguments - the format (arguments as options) is specific to shell.

my_func() {
local args
# I am used to linux getopt, getopts would work as well
if ! args=$(getopt -n "$my_func" -o "a:t:b:x:" -- "$@"); then
echo "my_func: Invalid arguments" >&2
return 1
fi
set -- "$args"
local optionsa title optionsb text
while (($#)); do
case "$1" in
-a) optionsa+=("$2"); shift; ;;
-t) title="$2"; shift; ;;
-b) optionsb+=("$2"); shift; ;;
-x) text="$2"; shift; ;;
*) echo "my_func: Error parsing argument: $1" >&2; return 1; ;;
esac
shift
done
my_command "${optionsa[@]}" "$title" "${optionsb[@]}" "$text"
}

my_func -a opta1 -a opta2 -t Title -b optb1 -b optb2 -x text

# or build the options list from arrays:
# ie. perform data serialization
args=()
for i in "${optionsa[@]}"; do
args+=(-a "$i")
done
args+=(-t "title")
for i in "${optionsb[@]}"; do args+=(-b "$i"); done
args+=(-x "text")
my_func "${args[@]}"

Generally if a function has constant and small count of arguments, just use the arguments. If functions get complicated with more edge cases, I recommend to parse the arguments like a man - makes the function versatile and abstract, easy to expand and implement edge cases and handle corner cases and errors, easy to understand by other programmers, easily readable and parsable by human eyes.

Because your example codes may some problems, I recommend to research how does quoting work in shelll, specifically how "${array[@]}" differ from ${array[@]}, research how [@] differ from [*], how does and when word splitting expansion is performed and how it affects the parameters. All the unquoted array expansions in your code suffer from word splitting - the spaces will not be preserved, also in the first example.

Elegant way for passing list to function as input arguments with incomplete list/missing list entries

Your function definition can stay the same:

def function1(a, b=5):
print(a)
print(b)

Your way of calling the function needs to change.

For positional arguments don't use a dict {}, use a list []:

x = [1, 2]
function1(*x) # prints 1 & 2

x = [1]
function1(*x) # prints 1 & 5

For named arguments use a dict (but then you have to call the values a and b, like the function does):

x = {"a": 1, "b": 2}
function1(**x) # prints 1 & 2

x = {"a": 1}
function1(**x) # prints 1 & 5

When used in a function call, the * operator unpacks lists, and the ** operators unpacks dicts into the function's arguments.

How to split list and pass them as separate parameter?

>>> argList = ["egg1", "egg2"]
>>> egg2(*argList)
egg1
egg2

You can use *args (arguments) and **kwargs (for keyword arguments) when calling a function.
Have a look at this blog on how to use it properly.



Related Topics



Leave a reply



Submit