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 Overflowfmt=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
It's more Pythonic to use the str.format method rather than the old %s printf style from C. It's also more Pythonic to use the builtin modules:
>>> import datetime
>>> args1 = 2014, 10, 01
>>> args2 = 2014, 10, 01, 12
>>> args3 = 2014, 10, 01, 12, 25
>>> '{0}'.format(datetime.datetime(*args1))
'2014-10-01 00:00:00'
>>> '{0}'.format(datetime.datetime(*args2))
'2014-10-01 12:00:00'
>>> '{0}'.format(datetime.datetime(*args3))
'2014-10-01 12:25:00'
If you want a more generalized answer to
What is the most pythonic way to insert a variable number of arguments into a string?
Then you could define a function to do that, with positional arguments for the required arguments, and keyword arguments for the optional arguments:
def format_args(arg1, arg2, arg3, arg4=0, arg5=0, arg6=0):
return '{0}, {1}, {2}, {3}, {4}, {5}'.format(
arg1, arg2, arg3, arg4, arg5, arg6)
usage:
>>> format_args(*args1)
'2014, 10, 1, 0, 0, 0'
>>> format_args(*args2)
'2014, 10, 1, 12, 0, 0'
>>> format_args(*args3)
'2014, 10, 1, 12, 25, 0'
Agree that using datetime is preferable to home rolled solutions. To answer the more general question of interpolating variable arguments in format strings that have different numbers of arguments: the % operator requires a specific number of arguments, but string.format only requires the minimum number. Provide a function that will pad your starting arguments to the longest possible with defaults, then you can feed that to format.
from itertools import chain
date_only = [ 2014, 2, 29 ]
date_and_time = [ 2014, 10, 23, 4, 20, 0 ]
defaults = [ 0 ] * 6 # the most arguments your format string requires
date_strs = [ "{} {} {}", "{} {} {} {} {} {}" ]
for s in date_strs:
print(s.format(*chain(date_only, defaults)))
print(s.format(*chain(date_and_time, defaults)))
Output:
2014 2 29
2014 10 23
2014 2 29 0 0 0
2014 10 23 4 20 0
Rather than hard coding your count, just count the number of valid braces in each template. A simplistic way of doing this is like this:
>>> "{} {} three {}".count("{}")
3
>>> "none".count("{}")
0
So your program would look something like this:
arguments = ["a", "b", "c", "d", "e", "f", "g"]
templates = [
"{{}} one",
"none",
"{} two {}",
"{} {} three {}",
"one2 {}",
"and {{literal}} braces {{}}"
]
start = 0
for template in templates:
count = template.count("{}")
print(template.format(*arguments[start : start + count]))
start += count
In the REPL:
>>> arguments = ["a", "b", "c", "d", "e", "f", "g"]
>>> templates = [
... "{} one",
... "none",
... "{} two {}",
... "{} {} three {}",
... "one2 {}",
... "and {{literal}} braces {{}}"
... ]
>>>
>>> start = 0
>>> for template in templates:
... count = template.count("{}")
... print(template.format(*arguments[start : start + count]))
... start += count
...
{} one
none
b two c
d e three f
one2 g
and {literal} braces {}
You could join all your templates using a character that you're unlikely to see in the templates or arguments, do the string interpolation, and then split the result.
templates = [
"{} one",
"none",
"{} two {}",
"{} {} three {}",
"one2 {}",
"and {{literal}} braces {{}}"
]
arguments = ["a", "b", "c", "d", "e", "f", "g"]
joined_template = chr(1).join(templates)
formatted_string = joined_template.format(*arguments)
formatted_templates = formatted_string.split(chr(1))
formatted_templates is now:
['a one',
'none',
'b two c',
'd e three f',
'one2 g',
'and {literal} braces {}']
I was under the impression that you also wanted to to be able to randomly add new items to the lists for each key. I was bored so I said why not and wrote the following code up. It will find the longest length of each entry of each key-value and put it in d_max, doesn't matter what type it is, as long as it can be converted to a string and also supports randomly adding things to the values (see last two lines of d). I tried to comment it well, but ask something if you need to.
d = {1: ['Spices', 39],
2: ['Cannons', 43],
3: ['Tea', 31],
4: ['Contraband', 46],
5: ['Fruit', 38],
6: ['Textiles', 44],
7: ['Odds and Ends', 100, 9999],
8: ['Candies', 9999, 'It\'s CANDY!']}
d_max = []
# Iterate over keys of d
for k in d:
# Length of the key
if len(d_max) <= 0:
d_max.append(len(str(k)) + 1)
elif len(str(k))+ 1 > d_max[0]:
d_max[0] = len(str(k)) + 1
# Iterate over the length of the value
for i in range(len(d[k])):
# If the index isn't in d_max then this must be the longest
# Add one to index because index 0 is the key's length
if len(d_max) <= i+1:
d_max.append(len(str(d[k][i])))
continue
# This is longer than the current one
elif len(str(d[k][i])) + 1 > d_max[i+1]:
d_max[i+1] = len(str(d[k][i])) + 1
for k,v in d.items():
list_var = [k] + v
# A list of values to unpack into the string
vals = []
# Add the value then the length of the space
for i in range(len(list_var)):
vals.append(list_var[i])
vals.append(d_max[i])
print(("{:<{}} " * len(list_var)).format(*vals))
Output:
1 Spices 39
2 Cannons 43
3 Tea 31
4 Contraband 46
5 Fruit 38
6 Textiles 44
7 Odds and Ends 100 9999
8 Candies 9999 It's CANDY!
If you wanted it all in one line then I'm afraid I can't help you :( There's also probably a cleaner way to do the second loop but that's all I could think up on a few hours of sleep.
do you mean you want to do something like:
list_var = [k] + v[:2]
This will work if the values list has too many items (It'll just remove the excess).
Mark Cidade's answer is right - you need to supply a tuple.
However from Python 2.6 onwards you can use format instead of %:
'{0} in {1}'.format(unicode(self.author,'utf-8'), unicode(self.publication,'utf-8'))
Usage of % for formatting strings is no longer encouraged.
This method of string formatting is the new standard in Python 3.0, and should be preferred to the % formatting described in String Formatting Operations in new code.
If you're using more than one argument it has to be in a tuple (note the extra parentheses):
'%s in %s' % (unicode(self.author), unicode(self.publication))
As EOL points out, the unicode() function usually assumes ascii encoding as a default, so if you have non-ASCII characters, it's safer to explicitly pass the encoding:
'%s in %s' % (unicode(self.author,'utf-8'), unicode(self.publication('utf-8')))
And as of Python 3.0, it's preferred to use the str.format() syntax instead:
'{0} in {1}'.format(unicode(self.author,'utf-8'),unicode(self.publication,'utf-8'))
You can join the *args to accomplish what you want:
def send_names(*args):
print('sometext, {0}'.format(', '.join(args)))
send_names('message1', 'message2', 'message3')
result:
sometext, message1, message2, message3
You cannot use *args or **kwargs to apply to a variable number of slots, no. You'd have to create the slots yourself based on the length:
','.join(['{}'] * len(args)).format(*args)
You can then interpolate the result of that into another template as needed. The above works with any type of argument normally accepted by a formatting slot.
Demo:
>>> args = ('foo', 'bar')
>>> ','.join(['{}'] * len(args)).format(*args)
'foo,bar'
>>> args = ('foo', 'bar', 'baz')
>>> ','.join(['{}'] * len(args)).format(*args)
'foo,bar,baz'
>>> args = (1, 2, 3)
>>> ','.join(['{}'] * len(args)).format(*args)
'1,2,3'
You can use the str.format() method, which lets you interpolate other variables for things like the width:
'Number {i}: {num:{field_size}.2f}'.format(i=i, num=num, field_size=field_size)
Each {} is a placeholder, filling in named values from the keyword arguments (you can use numbered positional arguments too). The part after the optional : gives the format (the second argument to the format() function, basically), and you can use more {} placeholders there to fill in parameters.
Using numbered positions would look like this:
'Number {0}: {1:{2}.2f}'.format(i, num, field_size)
but you could also mix the two or pick different names:
'Number {0}: {1:{width}.2f}'.format(i, num, width=field_size)
If you omit the numbers and names, the fields are automatically numbered, so the following is equivalent to the preceding format:
'Number {}: {:{width}.2f}'.format(i, num, width=field_size)
Note that the whole string is a template, so things like the Number string and the colon are part of the template here.
You need to take into account that the field size includes the decimal point, however; you may need to adjust your size to add those 3 extra characters.
Demo:
>>> i = 3
>>> num = 25
>>> field_size = 7
>>> 'Number {i}: {num:{field_size}.2f}'.format(i=i, num=num, field_size=field_size)
'Number 3: 25.00'
Last but not least, of Python 3.6 and up, you can put the variables directly into the string literal by using a formatted string literal:
f'Number {i}: {num:{field_size}.2f}'
The advantage of using a regular string template and str.format() is that you can swap out the template, the advantage of f-strings is that makes for very readable and compact string formatting inline in the string value syntax itself.
I prefer this (new 3.6) style:
name = 'Eugene'
f'Hello, {name}!'
or a multi-line string:
f'''
Hello,
{name}!!!
{a_number_to_format:.1f}
'''
which is really handy.
I find the old style formatting sometimes hard to read. Even concatenation could be more readable. See an example:
'{} {} {} {} which one is which??? {} {} {}'.format('1', '2', '3', '4', '5', '6', '7')