You'd use str.join() on the list without string formatting, then interpolate the result:
"Hello %s" % ', '.join(my_args)
Demo:
>>> my_args = ["foo", "bar", "baz"]
>>> "Hello %s" % ', '.join(my_args)
'Hello foo, bar, baz'
If some of your arguments are not yet strings, use a list comprehension:
>>> my_args = ["foo", "bar", 42]
>>> "Hello %s" % ', '.join([str(e) for e in my_args])
'Hello foo, bar, 42'
or use map(str, ...):
>>> "Hello %s" % ', '.join(map(str, my_args))
'Hello foo, bar, 42'
You'd do the same with your function:
function_in_library("Hello %s", ', '.join(my_args))
If you are limited by a (rather arbitrary) restriction that you cannot use a join in the interpolation argument list, use a join to create the formatting string instead:
function_in_library("Hello %s" % ', '.join(['%s'] * len(my_args)), my_args)
Answer from Martijn Pieters on Stack Overflowpython - argparse for unknown number of arguments and unknown names - Stack Overflow
Calling python function with an unknown number of arguments - Stack Overflow
templates - Formatting using a variable number of .format( ) arguments in Python - Stack Overflow
Trouble getting function to take unknown amount of arguments
If you know that the parameters will always be given in the format --name value or -name value you can do it easily
class ArgHolder(object):
pass
name = None
for x in sys.argv[1:]:
if name:
setattr(ArgHolder, curname, x)
name = None
elif x.startswith('-'):
name = x.lstrip('-')
Now you will have collected all arguments in the class ArgHolder which is a namespace. You may also collect the values in an instance of ArgHolder
Using Click we can build such a command:
import click
@click.command(help="Your description here")
@click.option("--someparameter", type=int, help="Description of someparameter")
@click.option("--p", type=int, help="Description of p")
@click.option("--anotherparam", type=str, help="Description of anotherparam")
def command(someparameter, p, anotherparam):
pass
if __name__ == '__main__':
command()
And you will have a help option automatically:
$ python command.py --help
Usage: command.py [OPTIONS]
Your description here.
Options:
--someparameter INTEGER Description of someparameter.
...
--help Show this message and exit.
If you need to get all unknown arguments, you can get them from a context in such way:
@click.command(context_settings=dict(
ignore_unknown_options=True,
allow_extra_args=True,
), add_help_option=False)
@click.pass_context
def command(ctx):
click.echo(ctx.args)
You can use the star or splat operator (it has a few names): for p in product(*lists) where lists is a tuple or list of things you want to pass.
def func(a,b):
print (a,b)
args=(1,2)
func(*args)
You can do a similar thing when defining a function to allow it to accept a variable number of arguments:
def func2(*args): #unpacking
print(args) #args is a tuple
func2(1,2) #prints (1, 2)
And of course, you can combine the splat operator with the variable number of arguments:
args = (1,2,3)
func2(*args) #prints (1, 2, 3)
Use the splat operator(*) to pass and collect unknown number of arguments positional arguments.
def func(*args):
pass
lis = [1,2,3,4,5]
func(*lis)
fmt=raw_input("what is the form? >>>")
nargs=fmt.count('{') #Very simple counting to figure out how many parameters to ask about
args=[]
for i in xrange(nargs):
args.append(raw_input("What is the value for parameter {0} >>>".format(i)))
fmt.format(*args)
#^ unpacking operator (sometimes called star operator or splat operator)
The easiest way is to simply try to format using whatever data you have, and if you get an IndexError you don't have enough items yet, so ask for another one. Keep the items in a list and unpack it using the * notation when calling the format() method.
format = raw_input("What is the format? >>> ")
prompt = "What is the value for parameter {0}? >>> "
parms = []
result = ""
if format:
while not result:
try:
result = format.format(*parms)
except IndexError:
parms.append(raw_input(prompt.format(len(parms))))
print result
So I have a function and it sometimes will need to take in a different amount of arguments. I'm trying something like this:
Def fun(*args):
balls = int(balls)
fun(balls)
But getting an error local variable not defined
But I can do this:
Def fun(*args):
Myballs = int(balls)
fun(balls)
I can't really see why the first one don't work and the second does and I just want the variable passed in with the same name.
What am I missing here?
I would like my function to be ready to take single string argument and act on it or take list of strings and iterate on it and act on each element.
Doing this way:
def foo( args ):
for arg in args:
print( arg )
single = 'first'
multi = ['first', 'second', 'third']
foo( single )
foo( multi )gives undesired result as it iterates over characters in may single string.
Doing alternative way:
def foo( *args ):
for arg in args:
print( arg )
single = 'first'
multi = ['first', 'second', 'third']
foo( single )
foo( multi )also gives undesired result, it takes multi as one argument instead of three.
What is the best practice in this case?
This way lies the path of madness. Good programs are built on reliable input. Saving a couple keystrokes is rarely worth the headaches that can be created down the road.
That said, here you go:
def foo( *args ):
for arg in args:
arg = arg if type(arg) is list else [arg]
for word in arg:
print word
Pretty much what it's doing is saying "if arg is a list, don't change it. If arg is not a list, make it one. Then do what you would do if it were a list (because everything is)".
I prefer this to the if/else option where they are handled differently because this way you're only maintaining one copy of the guts of the function, instead of trying to replicate it on both sides of the if/else.
You could just use 'if type(args) == list:' statement to treat lists and strings differently
I recently answered a question on S.O regarding this exact situation. You can't do this with traditional functions in Python.
You can do this by taking advantage of callables though, overloading the __call__ dunder of an int subclass.
In short, return a new instance of your self with the updated value (+ here):
class addByCallable(int):
def __call__(self, v):
return type(self)(self + v)
Now, you call it and get this 'form' of currying:
addByCallable(1)(2)(3) # 6
Which is as close as you can get to doing this in Python.
This is not possible since there is no way the function could know if it should return a number or a curried function.
There are various way of "cheating" to achieve some thing somewhat like this, for example you could call with no arguments in order to get the number rather than a function:
addByCurrying(1)(2) --> curried function
addByCurrying(1)(2)() --> the number 3
Which trick is most appropriate depends on what you are trying to achieve.
You can use "*args":
>>> custom_function = lambda *args: all(args)
>>> custom_function(1, 2, 3)
True
>>> custom_function(1, 2, 3, 0)
False
Which indeed is the same as just using "all":
>>> all(1, 2, 3)
True
>>> all(1, 2, 3, 0)
False
To be general, you can use "functools.reduce" to use any "2-parameters" function with any number of parameters (if their order doesn't matter):
import operator
import functools
c = lambda *args: functools.reduce(operator.and_, args)
(same results as before)
You can use argument unpacking via the * operator to process any number of arguments. You would have to resort to reduce (Python2) or functools.reduce (Python3) in order to combine them all with and in a single expression (as needed by the lambda):
from functools import reduce # only Py3
custom_function = lambda *args: reduce(lambda x, y: x and y, args, True)
Note: this is not the same as all, like many here suggest:
>>> all([1,2,3])
True
>>> 1 and 2 and 3
3
>>> custom_function(1,2,3)
3