Multiple Assignment Semantics

Multiple assignment semantics

One case when you need to include more structure on the left hand side of the assignment is when you're asking Python unpack a slightly more complicated sequence. E.g.:

# Works
>>> a, (b, c) = [1, [2, 3]]

# Does not work
>>> a, b, c = [1, [2, 3]]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need more than 2 values to unpack

This has proved useful for me in the past, for example, when using enumerate to iterate over a sequence of 2-tuples. Something like:

>>> d = { 'a': 'x', 'b': 'y', 'c': 'z' }
>>> for i, (key, value) in enumerate(d.iteritems()):
... print (i, key, value)
(0, 'a', 'x')
(1, 'c', 'z')
(2, 'b', 'y')

Semantics of SSA and multiple assignment

For SSA (Single Static Assignment), the two operand of a phi node should be two definition of a specific variable.

For your example, that means b=2, and a=1 are two definition for a single variable. And since b=2 will always run after a=1. Therefore, The definition b=2 will kill the definition of a=1. So, your phi(a,b) is in fact illegal.

phi's operands usually are definitions from two different execution pass of the program.

Multiple assignment and evaluation order in Python

In an assignment statement, the right-hand side is always evaluated fully before doing the actual setting of variables. So,

x, y = y, x + y

evaluates y (let's call the result ham), evaluates x + y (call that spam), then sets x to ham and y to spam. I.e., it's like

ham = y
spam = x + y
x = ham
y = spam

By contrast,

x = y
y = x + y

sets x to y, then sets y to x (which == y) plus y, so it's equivalent to

x = y
y = y + y

How does multiple assignment work?

How multiple assignment gets implemented depends on what implementation of Lua you are using. The implementation is free to do things anyway it likes as long as it preserves the semantics. That is, no matter how things get implemented, you should get the same result as if you had saved all the values in the RHS before assigning them to the LHS, as the Lua book explains.


If you are still curious about the actual implementation, one thing you can do is see what is the bytecode that gets produced for a certain program. For example, taking the following program

local x,y = 10, 11
x,y = y,x

and passing it to the bytecode compiler (luac -l) for Lua 5.2 gives

main <lop.lua:0,0> (6 instructions at 0x9b36b50)
0+ params, 3 slots, 1 upvalue, 2 locals, 2 constants, 0 functions
1 [1] LOADK 0 -1 ; 10
2 [1] LOADK 1 -2 ; 11
3 [2] MOVE 2 1
4 [2] MOVE 1 0
5 [2] MOVE 0 2
6 [2] RETURN 0 1

The MOVE opcode assigns the value in the right register to the left register (see lopcodes.h in the Lua source for more details). Apparently, what is going on is that registers 0 and 1 are being used for x and y and slot 2 is being used as a temporary extra slot. x and y get initialized with constants in the first two opcodes and in the next three 3 opcodes a swap is performed using the "temporary" second slot, kind of like you would do by hand:

tmp = y -- MOVE 2 1
y = x -- MOVE 1 0
x = tmp -- MOVE 0 2

Given how Lua used a different approach when doing a swapping assignment and a static initialization, I wouldn't be surprised if you got different results for different kinds of multiple assignments (setting table fields is probably going to look very different, specially since then the order should matter due to metamethods...). We would need to find the part in the source where the bytecode gets emitted to be 100% sure though. And as I mentioned before, all of this might vary between Lua versions and implementations, specially if you look at LuaJIT vs PUC Lua.

Python Multiple Assignment Statements In One Line

All credit goes to @MarkDickinson, who answered this in a comment:

Notice the + in (target_list "=")+, which means one or more copies. In foo = bar = 5, there are two (target_list "=") productions, and the expression_list part is just 5

All target_list productions (i.e. things that look like foo =) in an assignment statement get assigned, from left to right, to the expression_list on the right end of the statement, after the expression_list gets evaluated.

And of course the usual 'tuple-unpacking' assignment syntax works within this syntax, letting you do things like

>>> foo, boo, moo = boo[0], moo[0], foo[0] = moo[0], foo[0], boo[0] = [0], [0], [0]
>>> foo
[[[[...]]]]
>>> foo[0] is boo
True
>>> foo[0][0] is moo
True
>>> foo[0][0][0] is foo
True

Multiple Assignment syntax in C#

The assignment operator returns the value being assigned as it's result

The assignment operator (=) stores the value of its right-hand operand in the storage location, property, or indexer denoted by its left-hand operand and returns the value as its result.

So

x = y = z;

Is parsed as

x = (y = z);

And this is equivalent to

y = z;
x = y;

In the end, x, and y are assigned the same value as z (in this case, 3).

What is A, B = C in python?

s.accept() returns a tuple of two values : (host, port).

Therefore,

conn, address = s.accept()

is (apart that accept() is called twice) the same as

conn, address = s.accept()[0], s.accept()[1]

Difference between list assignment and tuple assignment?

They do the same thing. A tuple is a read-only version of a list. Usually you use parentheses (a, b) to create tuples versus square brackets [a, b] for lists, but the parentheses can sometimes be omitted. You could also write:

(a,b) = [1,2]

Or, perhaps most common:

a,b = 1,2

Multiple variable declaration

That's a "tuple" or "destructuring" assignment - see e.g. Multiple assignment semantics. cv2.threshold returns a tuple containing two values, so it's equivalent to:

temp = cv2.threshold(...)
ret = temp[0]
thresh = temp[1]

See Assignment Statements in the language reference:

If the target list is a comma-separated list of targets: The object must be an iterable with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets.



Related Topics



Leave a reply



Submit