17

Say I have a function

def foo(): return [1, 2, 3]

I want to interpolate the result of the function into a string to get "001 002 003". I've tried this:

f"{*foo():03d 03d 03d}"

But it produced SyntaxError: can't use starred expression here. Can I do this using an f-string?

planetp
  • 14,248
  • 20
  • 86
  • 160
  • 3
    `f"{' '.join(map('{:03d}'.format, foo()))}"`? – Ashwini Chaudhary Jan 27 '17 at 14:43
  • 2
    The suggestion works, but the f-string is redundant and the syntax verbose. One can just use the similar answer by @ev-kounis, without f-string. It seems f-strings do not improve the printing of lists. – divenex Feb 20 '18 at 09:52

5 Answers5

7

is this what you are looking for?

str_repr = ' '.join(map('{:03d}'.format, foo()))
print(str_repr)  # prints: 001 002 003

maybe the best thing about this solution is that it works with any list length and with minimal tweaking you can change the output format too.

Ma0
  • 15,057
  • 4
  • 35
  • 65
  • 4
    This works, but it does **not** make use of f-strings as requested. It may indeed be the best available Python solution, but it is verbose. I wish something like this `f"{foo():03d}"` would thread over the list. – divenex Feb 20 '18 at 11:07
6

Starred expressions are only allowed in few specific contexts, such as function calls, list/tuple/set literals, etc. An f-string placeholder is not one of them, apparently. You could format each element individually and join the strings, e.g.:

lst = foo()
s = ' '.join(f'{x:03d}' for x in lst)  # '001 002 003'

Generally, to format multiple values you have to use a separate placeholder for each value.

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
2

The * operator (similar rules exist for **) can only be used inside:

  • a function call: foo(*bar)
  • a list, tuple, or set literal: ['foo', *bar]
  • an assignment: foo, *bar = range(10)

It is not an expression and can therefore not be used inside the braces of f-strings.

L3viathan
  • 26,748
  • 2
  • 58
  • 81
1

You can also use the zfill method instead:

s_repr=" ".join([str(x).zfill(3) for x in foo()]) #not very PEP8 =S
0

For lists, f-strings do not seem to add much to what was already possible without them. An alternative, slightly simpler, solution without f-strings and without .join, which works for any list length, is the following

a = foo()
str_repr = ("{:03d} "*len(a)).format(*a)
print(str_repr)  # prints: 001 002 003
divenex
  • 15,176
  • 9
  • 55
  • 55