Not sure if this has been proposed before, but one thing I occasionally miss regarding tuple unpack is being able to do: first, second, *rest = something Also in for loops: for first, second, *rest in iterator: pass This seems to match the current meaning for starred variables in other contexts. What do you think? -- Gustavo Niemeyer http://niemeyer.net
On 10/7/05, Gustavo Niemeyer
Not sure if this has been proposed before, but one thing I occasionally miss regarding tuple unpack is being able to do:
first, second, *rest = something
Also in for loops:
for first, second, *rest in iterator: pass
This seems to match the current meaning for starred variables in other contexts.
Someone should really write up a PEP -- this was just discussed a week or two ago. I personally think this is adequately handled by writing: (first, second), rest = something[:2], something[2:] I believe that this wish is an example of "hypergeneralization" -- an incorrect generalization based on a misunderstanding of the underlying principle. Argument lists are not tuples [*] and features of argument lists should not be confused with features of tuple unpackings. [*] Proof: f(1) is equivalent to f(1,) even though (1) is an int but (1,) is a tuple. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Someone should really write up a PEP -- this was just discussed a week or two ago.
Heh.. I should follow the list more closely.
I personally think this is adequately handled by writing:
(first, second), rest = something[:2], something[2:]
That's an alternative indeed. But the the proposed way does look better: for item in iterator: (first, second), rest = item[2:], item[:2] ... vs. for first, second, *rest in iterator: ...
I believe that this wish is an example of "hypergeneralization" -- an incorrect generalization based on a misunderstanding of the underlying principle.
Thanks for trying so hard to say in a nice way that this is not a good idea. :-)
Argument lists are not tuples [*] and features of argument lists should not be confused with features of tuple unpackings.
Do you agree that the concepts are related? For instance:
def f(first, second, *rest): ... print first, second, rest ... f(1,2,3,4) 1 2 (3, 4)
first, second, *rest = (1,2,3,4) print first, second, rest 1 2 (3, 4)
[*] Proof: f(1) is equivalent to f(1,) even though (1) is an int but (1,) is a tuple.
"Extended *tuple* unpacking" was a wrong subject indeed. This is general unpacking, since it's supposed to work with any sequence. -- Gustavo Niemeyer http://niemeyer.net
Guido van Rossum wrote:
I personally think this is adequately handled by writing:
(first, second), rest = something[:2], something[2:]
That's less than satisfying because it violates DRY three times (once for mentioning 'something' twice, once for mentioning the index twice, and once for needing to make sure the index agrees with the number of items on the LHS).
Argument lists are not tuples [*] and features of argument lists should not be confused with features of tuple unpackings.
I'm aware of the differences, but I still see a strong similarity where this particular feature is concerned. The pattern of thinking is the same: "I want to deal with the first n of these things individually, and the rest collectively." -- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg.ewing@canterbury.ac.nz +--------------------------------------+
On Sunday 09 October 2005 22:44, Greg Ewing wrote:
I'm aware of the differences, but I still see a strong similarity where this particular feature is concerned. The pattern of thinking is the same: "I want to deal with the first n of these things individually, and the rest collectively."
Well stated. I'm in complete agreement on this matter. -Fred -- Fred L. Drake, Jr. <fdrake at acm.org>
Fred L. Drake, Jr. wrote:
On Sunday 09 October 2005 22:44, Greg Ewing wrote:
I'm aware of the differences, but I still see a strong similarity where this particular feature is concerned. The pattern of thinking is the same: "I want to deal with the first n of these things individually, and the rest collectively."
Well stated. I'm in complete agreement on this matter.
It also works for situations where "the first n items are mandatory, the rest are optional". This usage was brought up in the context of a basic line interpreter: cmd, *args = input.split() Another usage is to have a Python function which doesn't support keywords for its positional arguments (to avoid namespace clashes in the keyword dict), but can still unpack the mandatory arguments easily: def func(*args, **kwds): arg1, arg2, *rest = args # Unpack the positional arguments Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com
On 10/10/05, Nick Coghlan
It also works for situations where "the first n items are mandatory, the rest are optional". This usage was brought up in the context of a basic line interpreter:
cmd, *args = input.split()
That's a really poor example though. You really don't want a line interpreter to bomb if the line is empty!
Another usage is to have a Python function which doesn't support keywords for its positional arguments (to avoid namespace clashes in the keyword dict), but can still unpack the mandatory arguments easily:
def func(*args, **kwds): arg1, arg2, *rest = args # Unpack the positional arguments
Again, I'd be more comfortable if this was preceded by a check for len(args) >= 2. I should add that I'm just -0 on this. I think proponents ought to find better motivating examples that aren't made-up. Perhaps Raymond's requirement would help -- find places in the standard library where this would make code more readable/maintainable. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
On 10/10/05, Nick Coghlan
cmd, *args = input.split()
These examples also have a reasonable implementation using list.pop(), albeit one that requires more typing. On the plus side, it does not violate DRY and is explicit about the error cases. args = input.split() try: cmd = input.pop(0) except IndexError: cmd = ''
def func(*args, **kwds): arg1, arg2, *rest = args # Unpack the positional arguments
rest = args # or args[:] if you really did want a copy try: arg1 = rest.pop(0) arg2 = rest.pop(0) except IndexError: raise TypeError("foo() takes at least 2 arguments") paul
participants (6)
-
Fred L. Drake, Jr.
-
Greg Ewing
-
Guido van Rossum
-
Gustavo Niemeyer
-
Nick Coghlan
-
Paul Du Bois