33

Does anybody know the reasoning as to why the unary (*) operator cannot be used in an expression involving iterators/lists/tuples?

Why is it only limited to function unpacking? or am I wrong in thinking that?

For example:

>>> [1,2,3, *[4,5,6]]
File "<stdin>", line 1
[1,2,3, *[4,5,6]]
        ^
SyntaxError: invalid syntax

Why doesn't the * operator:

[1, 2, 3, *[4, 5, 6]] give [1, 2, 3, 4, 5, 6]

whereas when the * operator is used with a function call it does expand:

f(*[4, 5, 6]) is equivalent to f(4, 5, 6)

There is a similarity between the + and the * when using lists but not when extending a list with another type.

For example:

# This works
gen = (x for x in range(10))

def hello(*args):
    print args    
hello(*gen)

# but this does not work
[] + gen
TypeError: can only concatenate list (not "generator") to list
3
  • What are you expecting from that usage? I mean, why would you want to do that? Commented Jan 13, 2016 at 12:26
  • ok ill update my question Commented Jan 13, 2016 at 12:27
  • It looks like two separate question: the first is more syntax related, the second is just the behaviour of list.__add__ Commented Jan 13, 2016 at 13:18

3 Answers 3

48

Unpacking in list, dict, set, and tuple literals has been added in Python 3.5, as described in PEP 448:

Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37) on Windows (64 bits).

>>> [1, 2, 3, *[4, 5, 6]]
[1, 2, 3, 4, 5, 6]

Here are some explanations for the rationale behind this change. Note that this does not make *[1, 2, 3] equivalent to 1, 2, 3 in all contexts. Python's syntax is not intended to work that way.

Sign up to request clarification or add additional context in comments.

3 Comments

use full info, but we discussing python-2.7 ( see tags in question)
Seems like they hadn't considered the use of the * within a container when making python 2.7?
@AndriyIvaneyko this answers the question as asked. The OP wants to know the reasoning, not how to do it in another way in Py2.7.
7

The asterisk * isn't simply unary operator, it's argument-unpacking operator for functions definitions and functions calls.

So * supposed to be used only to work with function params and not with lists, tuples etc.

NOTE: starting from python3.5, * could be used not only with functions params, @B. M's answer greatly describes that change in python.

If you need to concat lists use concatenation instead list1 + list2 to get desired result. To concatenate list and generator simply pass generator to list type object, prior concatenating with another list:

gen = (x for x in range(10))
[] + list(gen)

2 Comments

It works in function calls as well as function definitions. It seems a bit like you're implying it only works in the latter case, so you might wnat to edit wording.
@SuperBiasedMan Thanks, for correction i've updated answer.
4

This is not supported. Python 3 gives a better message (though Python 2 does not support * in the left part of an assignment, afaik):

Python 3.4.3+ (default, Oct 14 2015, 16:03:50) 
>>> [1,2,3, *[4,5,6]]
  File "<stdin>", line 1
SyntaxError: can use starred expression only as assignment target
>>> 

f(*[4,5,6]) is equivalent to f(4,5,6)

Function argument unfolding is a special case.

1 Comment

Thank you for pointing out python 3, I have just tried it out and it does work in python 3.5.1 >>> [*[1,2,3,4]] => [1, 2, 3, 4] I wasnt aware of that. It even works with generators :) very cool [1,2,3, (x for x in range(10))]

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.