as we all know, * (asterisk) can be used to "inline" or "flatten" a tuple into an argument list, i.e.:
def f(a, b, c): ... x = (1,2,3) f(*x) so... mainly for symmetry's sake, why not make a "flattening" operator that also works outside the context of function calls? for example: a = (1,2,3) b = (4,5) c = (*a, *b) # ==> (1,2,3,4,5) yeah, a + b would also give you the same result, but it could be used like format-strings, for "templating" tuples, i.e. c = (*a, 7, 8, *b) i used to have a concrete use-case for this feature some time ago, but i can't recall it now. sorry. still, the main argument is symmetry: it's a syntactic sugar, but it can be useful sometimes, so why limit it to function calls only? allowing it to be a generic operator would make things like this possible: f(*args, 7) # an implied last argument, 7, is always passed to the function today you have to do f(*(args + (7,))) which is quite ugly. and if you have to sequences, one being a list and the other being a tuple, e.g. x = [1,2] y = (3,4) you can't just x+y them. in order to concat them you'd have to use "casting" like f(*(tuple(x) + y)) instead of f(*x, *y) isn't the latter more elegant? just an idea. i'm sure people could come up with more creative use-cases of a standard "flattening operator". but even without the creative use cases -- isn't symmetry strong enough an argument? why are function calls more important than regular expressions? and the zen proves my point: (*) Beautiful is better than ugly --> f(*(args + (7,))) is ugly (*) Flat is better than nested --> less parenthesis (*) Sparse is better than dense --> less noise (*) Readability counts --> again, less noise (*) Special cases aren't special enough to break the rules --> then why are function calls so special? the flattening operator would work on any sequence (having __iter__ or __next__), not just tuples and lists. one very useful feature i can thik of is "expanding" generators, i.e.: print xrange(10) # ==> xrange(10) print *xrange(10) # ==> (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) i mean, python already supports this half-way: >>> def f(*args): ... print args ... >>> f(*xrange(10)) (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) so... why can't i just do "print *xrange(10)" directly? defining a function just to expand a generator? well, i could use "list(xrange(10))" to expand it, but it's less intuitive. the other way is list-comprehension, [x for x in xrange(10)], but isn't *xrange(10) more to-the-point? also, "There should be one-- and preferably only one --obvious way to do it"... so which one? (*) list(xrange(10)) (*) [x for x in xrange(10)] (*) [].extend(xrange(10)) (*) f(*xrange(10)) they all expand generators, but which is the preferable way? and imagine this: f(*xrange(10), 7) this time you can't do *(xrange(10) + (7,)) as generators do not support addition... you'd have to do *(tuple(xrange(10)) + (7,)) which is getting quite long already. so as you can see, there are many inconsistencies between function-call expressions and regular expressions, that impose artificial limitations on the language. after all, the code is already in there to support function-call expressions. all it takes is adding support for regular exoressions. what do you think? should i bring it up to python-dev? -tomer -- http://mail.python.org/mailman/listinfo/python-list