Tuple pack/unpack and the definition of AST Assign nodes

In porting one of the old peephole optimizations to the new AST compiler I noticed something weird going on with the following code: a, b, c = 1, 2, 3 Now, as you would expect this gets parsed into an Assign node. That Assign node looks like the following: Assign.targets = [Tuple(Name(a), Name(b), Name(c))] Assign.value = Tuple(1, 2, 3) What's weird here is that Assign.targets is an asdl_seq ... why are we wrapping the names in a Tuple() node? Shouldn't it look something more like this: Assign.targets = [Name(a), Name(b), Name(c)] I understand that parsing the testlist might yield a tuple and it was thus easier to just use the tuple rather than unpack it into an asdl_seq ... but if this was the intention, then why is Assign.targets an expr* rather than a plain old expr? Cheers, Tom

Thomas Lee wrote:
In porting one of the old peephole optimizations to the new AST compiler I noticed something weird going on with the following code:
a, b, c = 1, 2, 3
Now, as you would expect this gets parsed into an Assign node. That Assign node looks like the following:
Assign.targets = [Tuple(Name(a), Name(b), Name(c))] Assign.value = Tuple(1, 2, 3)
What's weird here is that Assign.targets is an asdl_seq ... why are we wrapping the names in a Tuple() node? Shouldn't it look something more like this:
Assign.targets = [Name(a), Name(b), Name(c)]
I understand that parsing the testlist might yield a tuple and it was thus easier to just use the tuple rather than unpack it into an asdl_seq ... but if this was the intention, then why is Assign.targets an expr* rather than a plain old expr?
I haven't looked at that code recently, but I believe the ADSL sequence in the assignment node is for statements where there are actually multiple assignment targets, such as:
p = x, y = 1, 2 p, x, y ((1, 2), 1, 2)
Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org

Nick Coghlan wrote:
I haven't looked at that code recently, but I believe the ADSL sequence in the assignment node is for statements where there are actually multiple assignment targets, such as:
p = x, y = 1, 2 p, x, y ((1, 2), 1, 2)
Cheers, Nick.
Ah I see. A quick test verifies exactly this: >>> import _ast >>> ast = compile("p = x, y = 1, 2", "<string>", "exec", _ast.PyCF_ONLY_AST) >>> ast.body[0] <_ast.Assign object at 0xb7d0122c> >>> ast.body[0].targets [<_ast.Name object at 0xb7d0124c>, <_ast.Tuple object at 0xb7d0128c>] >>> ast.body[0].value <_ast.Tuple object at 0xb7d0132c> >>> I thought this would have been implemented as nested Assign nodes, but I'm obviously wrong. :) Thanks for the clarification. Cheers, T

Thomas Lee wrote:
Nick Coghlan wrote:
I haven't looked at that code recently, but I believe the ADSL sequence in the assignment node is for statements where there are actually multiple assignment targets, such as:
p = x, y = 1, 2 p, x, y ((1, 2), 1, 2)
Cheers, Nick.
Ah I see. A quick test verifies exactly this:
import _ast ast = compile("p = x, y = 1, 2", "<string>", "exec", _ast.PyCF_ONLY_AST) ast.body[0] <_ast.Assign object at 0xb7d0122c> ast.body[0].targets [<_ast.Name object at 0xb7d0124c>, <_ast.Tuple object at 0xb7d0128c>] ast.body[0].value <_ast.Tuple object at 0xb7d0132c>
I thought this would have been implemented as nested Assign nodes, but I'm obviously wrong. :) Thanks for the clarification.
It's one of the key differences between Python's "assignment as a statement" and C-style "assignment as an expression" - nested Assignment nodes are meaningful with the latter approach, but nonsensical with the way Python defines assignment (the rightmost expression is evaluated once and then assigned to each of the target expressions from left to right). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org
participants (2)
-
Nick Coghlan
-
Thomas Lee