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:
- 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"
- 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:
- 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"
- 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
Why Is _Init_() Always Called After _New_()
Retrieve Links from Web Page Using Python and Beautifulsoup
How to Check If a String Represents an Int, Without Using Try/Except
How to Add New Keys to a Dictionary
How to Check If a String Is a Substring of Items in a List of Strings
Convert Python Dict into a Dataframe
What Is an Alternative to Execfile in Python 3
Use Numpy Array in Shared Memory For Multiprocessing
How to Send an Email With Gmail as Provider Using Python
Simpler Way to Create Dictionary of Separate Variables
How to Fix "Attempted Relative Import in Non-Package" Even With _Init_.Py
Concatenate Strings from Several Rows Using Pandas Groupby
How to Install a Python Package With a .Whl File
Reading Binary File and Looping Over Each Byte
How to Install Pip With Python 3
How to Save and Load Cookies Using Python + Selenium Webdriver