There are two alternatives for f_expression: a comma separated list of or_exprs, optionally preceded by asterisks, or a single yield_expression. Note the yield_expression does not allow an asterisk.

I assume the intention was that the comma-separated list alternative is only chosen when there's at least one comma, but the grammar doesn't actually say that. I feel like the repetition operator at the end should have been a + instead of a *.

So f"{*1}" would be a syntax error because there's an asterisk, but no comma. f"{*1,*2}" is syntactically valid, but a type error because 1 and 2 aren't iterable. f"{*[1], *[2]}" is valid and acts the same as f"{1,2}". So the asterisk is allowed because it acts as the splat operator in tuples, which can be written without parentheses in f-expressions.

Note that using or_expr as the operand to * does not mean that a bitwise or-operator has to be used there - it just means that the bitwise or-operator is the first operator in the precedence-hierachy that would be allowed as an operand to *. So it's just about setting the precedence of prefix * vs. other expressions. I believe or_expr is consistently used as the operand to prefix * everywhere in the grammar (that is, everywhere where prefix * is followed by an expression as opposed to a parameter name).

Answer from sepp2k on Stack Overflow
Top answer
1 of 3
17

There are two alternatives for f_expression: a comma separated list of or_exprs, optionally preceded by asterisks, or a single yield_expression. Note the yield_expression does not allow an asterisk.

I assume the intention was that the comma-separated list alternative is only chosen when there's at least one comma, but the grammar doesn't actually say that. I feel like the repetition operator at the end should have been a + instead of a *.

So f"{*1}" would be a syntax error because there's an asterisk, but no comma. f"{*1,*2}" is syntactically valid, but a type error because 1 and 2 aren't iterable. f"{*[1], *[2]}" is valid and acts the same as f"{1,2}". So the asterisk is allowed because it acts as the splat operator in tuples, which can be written without parentheses in f-expressions.

Note that using or_expr as the operand to * does not mean that a bitwise or-operator has to be used there - it just means that the bitwise or-operator is the first operator in the precedence-hierachy that would be allowed as an operand to *. So it's just about setting the precedence of prefix * vs. other expressions. I believe or_expr is consistently used as the operand to prefix * everywhere in the grammar (that is, everywhere where prefix * is followed by an expression as opposed to a parameter name).

2 of 3
0

Just stumbled on this question and thought it might be due to symmetry with other related statements, for example:

a = 1,
a = (1,)
a = 1,*()
a = *[1],

all result in a being assigned to a tuple containing 1. Note however, that not including single a comma, e.g.:

return *[1]

is, instead, a SyntaxError. This mirrors behaviour in f-strings and is likely because Python "the language" is inextricably tied to CPython "the implementation".

Taking look at CPython 3.11's grammar shows that the rules pointed to by the OP don't exist in Grammar/python.gram. What exists instead is the following rule:

fstring[expr_ty]: star_expressions

saying that an fstring is just a star_expression, as could be used in various other places (e.g. by the assignments above). The rules appearing in the language docs are just an abridged version of the full grammar which defines star_expressions more generally.

Hence I'm not sure how relevant it is to separate Python from CPython here, as people often try to do. The semantics implied by a convenient change to CPython's parser were codified by Python the language.

🌐
Reddit
reddit.com › r/learnpython › f-strings with star variables.
r/learnpython on Reddit: F-strings with Star Variables.
March 2, 2019 -

Hello everybody

Is there an F-string equivalent to do something like this?

test_list = [1, 2, 3, 4]
print("{} {} {} {}".format(*test_list))

Obviously this doesn't work:

print(f"{*test_list}")

Was wondering if there was something that would allow it for F-string?

Discussions

Specialise syntax error of **dict in f-string field
BPO 41064 Nosy @terryjreedy, @ericvsmith, @pablogsal, @E-Paine, @JNCressey PRs #25006 Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state. Show more details GitHub fields:... More on github.com
🌐 github.com
7
June 21, 2020
python - Why can't I use a starred expression? - Stack Overflow
Update: since python 3.6, you could also use string interpolation - f-strings! These are described in PEP-498, and some examples can be found in Python documentation. There are many more uses to starred expression than just creating a new list/tuple/dictionary. More on stackoverflow.com
🌐 stackoverflow.com
November 18, 2016
I can't understand starred expression in python - Stack Overflow
Adding the star will "expand" the generator of the map function into multiple parameters ... Its a one-liner - better? well ... it asks for input and issues the string.find() method on each character between ascii 97 and 123 for your given input. find returns -1 if not found, else the first(!) occurence of the character in your input. the result of map is a generator in python3 ... More on stackoverflow.com
🌐 stackoverflow.com
F-strings with Star Variables.
Why use a f-string when you can just do: print(*test_list) More on reddit.com
🌐 r/learnpython
18
5
March 2, 2019
🌐
TutorialsPoint
tutorialspoint.com › how-to-unpack-using-star-expression-in-python
How to unpack using star expression in Python?
Python's star expression (*) allows you to unpack sequences without knowing their exact length in advance. This solves the limitation of traditional unpacking where you must match the number of variables to sequence elements.
🌐
Iditect
iditect.com › faq › python › what-does-a-star-asterisk-do-in-fstring-in-python.html
What does a star (asterisk) do in f-string in python?
In Python f-strings (formatted string literals), the asterisk (*) is used as a prefix to perform various formatting operations. The asterisk is used to unpack iterables (lists, tuples, etc.) and dictionaries when formatting strings. This allows you to include the elements of these iterables ...
🌐
Python
peps.python.org › pep-0701
PEP 701 – Syntactic formalization of f-strings | peps.python.org
November 15, 2022 - FSTRING_START: This token includes the f-string prefix (f/F/fr) and the opening quote(s). FSTRING_MIDDLE: This token includes a portion of text inside the string that’s not part of the expression part and isn’t an opening or closing brace.
🌐
Real Python
realpython.com › python-f-strings
Python's F-String for String Interpolation and Formatting – Real Python
November 30, 2024 - The syntax is similar to what you used with .format(), but it’s less verbose. You only need to start your string literal with a lowercase or uppercase f and then embed your values, objects, or expressions in curly brackets at specific places:
Find elsewhere
🌐
Yaoyao
yaoyao.codes › python › 2016 › 09 › 25 › python-starred-expression
Python: *expression - Yao's blog
September 25, 2016 - The starred expression will catch the remainder values of RHS · E.g. if seq is a slicable sequence, all the following assignments are equivalent if seq has at least 2 elements:
🌐
Python
peps.python.org › pep-0498
PEP 498 – Literal String Interpolation | peps.python.org
That is, the string must end with ... if it starts with a single quote it must end with a single quote, etc. This implies that any code that currently scans Python code looking for strings should be trivially modifiable to recognize f-strings (parsing within an f-string is another matter, of course). Once tokenized, f-strings are parsed in to literal strings and expressions...
🌐
Python
bugs.python.org › issue41064
Issue 41064: Specialise syntax error of **dict in f-string field - Python tracker
June 21, 2020 - This issue tracker has been migrated to GitHub, and is currently read-only. For more information, see the GitHub FAQs in the Python's Developer Guide · This issue has been migrated to GitHub: https://github.com/python/cpython/issues/85236
🌐
Pylint
pylint.readthedocs.io › en › v3.1.1 › user_guide › checkers › features.html
Pylint features - Pylint 3.1.1 documentation
May 13, 2024 - Return with argument inside generator Used when a "return" statement with an argument is found in a generator function or method (e.g. with some "yield" statements). This message can't be emitted when using Python >= 3.3. ... Starred assignment target must be in a list or tuple Emitted when a star expression is used as a starred assignment target.
🌐
GitHub
gist.github.com › listty › e943b3093f6a0f6a16c72b08cdef76a2
Star in f-strings.py · GitHub
June 21, 2020 - Star in f-strings.py · This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters ·
🌐
Notebook Community
notebook.community › osunderdog › PythonLearning › PythonZipExploration
Studying "starred expressions" in Python
No, the definition of the function requires that there are two and only two parameters. If I add a star to the parameter, then I am specifying that there may be one or two parameters.
🌐
GeeksforGeeks
geeksforgeeks.org › starred-expression-in-python
Starred Expression in Python | GeeksforGeeks
February 1, 2025 - Starred expression (*) in Python is used to unpack elements from iterables. It allows for extracting multiple values from a sequence and packing them into a list or a tuple or even collecting extra arguments in a function.
🌐
GitHub
github.com › python › cpython › issues › 85236
Specialise syntax error of **dict in f-string field · Issue #85236 · python/cpython
June 21, 2020 - assignee = None closed_at = <Date 2021-03-24.19:34:39.459> created_at = <Date 2020-06-21.12:32:38.555> labels = ['interpreter-core', 'type-bug', '3.8', '3.9', '3.10'] title = 'Specialise syntax error of **dict in f-string field' updated_at = <Date 2021-03-24.19:34:42.616> user = 'https://github.com/JNCressey'
Author   python
Top answer
1 of 3
60

It's because this:

(a)

Is just a value surrounded by parenthesis. It's not a new tuple object. So your expression:

>>> '%d %d' % (*a)

will get translated to:

>>> '%d %d' % * a

which is obviously wrong in terms of python syntax.

In order to create a new tuple, with one expression as an initializer, you need to add a ',' after it:

>>> '%d %d' % (*a,)

Note: unless a is a generator, in this particular situation you could just type:

>>> '%d %d' % a

Also, if I may suggest something: you could start using new-style formating expressions. They are great!

>>> "{} {}".format(*a)

You can read more about them in those two paragraphs of python documentation, also there is this great website. The line above uses argument unpacking mechanism described below.

Update: since python 3.6, you could also use string interpolation - f-strings! These are described in PEP-498, and some examples can be found in Python documentation.

Starred Expressions

There are many more uses to starred expression than just creating a new list/tuple/dictionary. Most of them are described in PEP 3132, and PEP 448.

All of them come down to two kinds:

R-value unpacking:

>>> a, *b, c = range(5)
# a = 0
# b = [1, 2, 3]
# c = 4
>>> 10, *range(2)
(10, 0, 1)

Iterable / dictionary object initialization (notice that you can unpack dictionaries inside lists too!):

>>> [1, 2, *[3, 4], *[5], *(6, 7)]
[1, 2, 3, 4, 5, 6, 7]
>>> (1, *[2, 3], *{"a": 1})
(1, 2, 3, 'a')
>>> {"a": 1, **{"b": 2, "c": 3}, **{"c": "new 3", "d": 4}}
{'a': 1, 'b': 2, 'c': 'new 3', 'd': 4}

Of course, the most often seen use is arguments unpacking:

positional_arguments = [12, "a string", (1, 2, 3), other_object]
keyword_arguments = {"hostname": "localhost", "port": 8080}
send(*positional_arguments, **keyword_arguments)

which would translate to this:

send(12, "a string", (1, 2, 3), other_object, hostname="localhost", port=8080)

This topic has already been covered to a substantial extent in another Stack Overflow question.

2 of 3
3

My question, why?

Because your python syntax doesn't allow that. It's defined that way, so there's no real "why".

also, it's unnecessary.

"%d %d" % a

would work.

So, you'd need to convert your expansion to a tuple – and the right way of doing that would be, as pointed out by Lafexlos, be

"%d %d" % (*a,)
🌐
Stack Overflow
stackoverflow.com › questions › 50084454 › i-cant-understand-starred-expression-in-python
I can't understand starred expression in python - Stack Overflow
Adding the star will "expand" the generator of the map function into multiple parameters ... Its a one-liner - better? well ... it asks for input and issues the string.find() method on each character between ascii 97 and 123 for your given input. find returns -1 if not found, else the first(!) occurence of the character in your input. the result of map is a generator in python3 - the * just unpacks each value and provides it to print.
🌐
Career Karma
careerkarma.com › blog › python › python f strings: the ultimate guide
Python f Strings: The Ultimate Guide | Career Karma
December 1, 2023 - Python f strings are a new tool you can use to put expressions inside string literals. The advantages of using f strings over previous options are numerous. f strings are easier to read. They work well even when you’re working with many values. This tutorial discussed, with reference to examples, how f strings compare to other string formatting options, and how to use f strings in your code. Now you have the knowledge you need to start working with Python f strings like a professional developer!
🌐
Medium
medium.com › geekculture › python-f-string-codes-i-use-every-day-e03558f12057
Python f-string codes I use everyday by pawjast | Geek Culture
January 9, 2024 - This article covers the most common Python f-string formats and provides practical examples of how to use them.