My code
$ python Python 3.5.2 |Continuum Analytics, Inc.| (default, Jul 2 2016, 17:53:06) [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> a = (1, 2) >>> '%d %d %d' % (0, *a) '0 1 2' >>> '%d %d %d' % (*a, 3) '1 2 3' >>> '%d %d' % (*a) File "<stdin>", line 1 SyntaxError: can't use starred expression here >>>
My question, why?
In a more serious tone: I'd like an answer, or a reference, that details all the ins and outs of using a starred expression, as it happens that I am sometimes surprised from its behaviours...
To reflect some of the enlightening comments that immediately followed my question I add the following code
>>> '%d %d' % (, *a) File "<stdin>", line 1 '%d %d' % (, *a) ^ SyntaxError: invalid syntax >>> '%d %d' % (*a,) '1 2' >>>
(I had tried the (, a)
part before posting the original question but I've omitted it 'cause the error was not related to the starring.)
There is a syntax, in python ≥ 3.5, that "just works" but nevertheless I would like some understanding.
The starred expression will create a list object, although we start with a tuple object. Starred expressions can be used with more than just tuples, and we can apply this technique for other iterables (e.g., lists, strings).
Starred expressions are only allowed as assignment targets, using them anywhere else (except for star-args in function calls, of course) is an error.
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.
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,)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With