f-string syntax for unpacking a list with brace suppression

PythonPython 3.xString FormattingPython 3.6F String

Python Problem Overview


I have been examining some of my string format options using the new f-string format. I routinely need to unpack lists and other iterables of unknown length. Currently I use the following...

>>> a = [1, 'a', 3, 'b']
>>> ("unpack a list: " + " {} "*len(a)).format(*a)
'unpack a list:  1  a  3  b '

This, albeit a bit cumbersome, does the job using pre-3.6 .format notation. The new f-string format option is interesting given runtime string concatenation. It is the replication of the number of {} that I am having problems with. In my previous example, I simply created the necessary structure and unpacked within the .format() section.

Attempts to do this yielded one variant that worked, however:

1) Both curly brackets together doesn't unpack...
>>> 'unpack a list'  f' {{*a}}'
'unpack a list {*a}'
2) Adding spaces around the interior {} pair:

This works but leaves opening and closing braces {, } present:

>>> 'unpack a list'  f' { {*a} }'
"unpack a list {1, 3, 'a', 'b'}"
2b) Concatenating the variants into one f-string

This made the look and syntax better, since the evaluation, apparently, is from left to right. This, however, still left the enclosing curly brackets present:

>>> f'unpack a list { {*a} }'
"unpack a list {1, 3, 'a', 'b'}"
3) Tried automatic unpacking with just {a}

Perhaps, I was overthinking the whole procedure and hoping for some form of automatic unpacking. This simply yielded the list representation with the curly brackets being replaced with [] :

>>> f'unpack a list {a}'
"unpack a list [1, 'a', 3, 'b']"

What is required to suppress the curly brackets in variant (2) above, or must I keep using the existing .format() method? I want to keep it simple and use the new capabilities offered by the f-string and not revert back beyond the python versions which pre-date what I am currently comfortable with. I am beginning to suspect that f'strings' do not offer a complete coverage of what is offered by its .format() sibling. I will leave it at that for now, since I haven't even ventured into the escape encoding and the inability to use \ in an f-string. I have read the PEP and search widely, however, I feel I am missing the obvious or what I wish for is currently not possible.

EDIT several hours later:

4) Use subscripting to manually slice off the brackets: str(a)[1:-2]

I did find this variant which will serve for some cases that I need

f'unpack a list: {str(a)[1:-2]}'
"unpack a list: 1, 'a', 3, 'b"

But the slicing is little more than a convenience and still leaves the string quotes around the resultant.

5) and the final solution from @SenhorLucas
 a = np.arange(10)

print(f"{*a,}")
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

Unpacking with trailing comma.

Python Solutions


Solution 1 - Python

Just add a comma after the unpacked list.

a = [1, 2, 3]
print(f"Unpacked list: {*a,}")
# Unpacked list: (1, 2, 3)

There is a longer explanation to this syntax in this thread.

Solution 2 - Python

Since any valid Python expression is allowed inside the braces in an f-string, you can simply use str.join() to produce the result you want:

>>> a = [1, 'a', 3, 'b']
>>> f'unpack a list: {" ".join(str(x) for x in a)}'
'unpack a list: 1 a 3 b'

You could of course also write a helper function, if your real-world use case makes the above more verbose than you'd like:

def unpack(s):
    return " ".join(map(str, s))  # map(), just for kicks

>>> f'unpack a list: {unpack(a)}'
'unpack a list: 1 a 3 b'

Solution 3 - Python

Simple Python is probably more clear:

>>>  'unpack a list: ' + ' '.join(str(x) for x in a)
'unpack a list: 1 a 3 b'

With slicing:

>>> 'unpack a list: ' + ' '.join([str(x) for x in a][1:3])
'unpack a list: a 3'

Solution 4 - Python

I don't think that this is the way f-Strings are meant to be used. At best I can imagine preparing a print() compatible tuple, like:

mixed = [1, "list_string", 2]
number = 23
answer = 46

info = 'Content:', *mixed, f'{number} {answer}'
print(*info)  # default sep=' '

Output

Content: 1 list_string 2 23 46

Solution 5 - Python

I made this a while back, to include commas Oxford style.

def unpack_list(lst):  # Oxford comma
    if not isinstance(lst, str):
        lst = [str(item) for item in lst]
    if len(lst) == 0:
        return
    if len(lst) == 1:
        return ", ".join(lst)
    if len(lst) == 2:
        return ", and ".join(lst) 
    else:
        first_part = lst[:-1]
        last_part = lst[-1]
        return ", ".join(first_part) + ", and " + last_part

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNaNView Question on Stackoverflow
Solution 1 - PythonSenhorLucasView Answer on Stackoverflow
Solution 2 - PythonZero PiraeusView Answer on Stackoverflow
Solution 3 - PythonGringo SuaveView Answer on Stackoverflow
Solution 4 - PythonErnesto HerreraView Answer on Stackoverflow
Solution 5 - PythonLewi UbergView Answer on Stackoverflow