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).
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).
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.
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?
Specialise syntax error of **dict in f-string field
python - Why can't I use a starred expression? - Stack Overflow
I can't understand starred expression in python - Stack Overflow
F-strings with Star Variables.
Videos
The error occurs because (a) is just a value surrounded by parenthesis. It's not a new tuple object.
Thus, '%d %d' % (*a) is equivalent to '%d %d' % * a, which is obviously wrong in terms of python syntax.
To create a new tuple, with one expression as an initializer, use a comma after that expression:
>>> '%d %d' % (*a,)
'1 2'
Of course, since a is already a tuple, we can use it directly:
>>> '%d %d' % a
'1 2'
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,)
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.
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,)