bsr
bsr

Reputation: 58662

Double assignment in python

Please see the code here

move_from, move_to = [
        (item['path'], prev_item['path']),
        (prev_item['path'], item['path']),
    ][item['op'] == 'add']

What is assigned to move_from and move_to. It looks like double assignment, but don't see two on the right (I am a non python programmer) I am trying to port to Javascript, how would it look like?

Thanks.

Upvotes: 0

Views: 590

Answers (4)

bsoist
bsoist

Reputation: 785

This

[
(item['path'], prev_item['path']),
(prev_item['path'], item['path']),
]

is a Python list. The first (0) item is

(item['path'], prev_item['path'])

and the second (1) is

(prev_item['path'], item['path'])

the boolean here

[item['op'] == 'add']

evaluates to True of False ( 1 or 0 ) so that one of those items is chosen.

For example, if item['op'] does equal 'add', then the result is

move_from, move_to = prev_item['path'], item['path']

EDIT: You asked for JS code. This might do it. NOTE that I've assumed most variables are global since I don't know in what context you will use this.

String.prototype.rsplit = function(sep, maxsplit) {
    var split = this.split(sep);
    return maxsplit ? [ split.slice(0, -maxsplit).join(sep) ].concat(split.slice(-maxsplit)) : split;
}

function _optimize_using_move(prev_item, item) {
    prev_item['op'] = 'move';
    if (item['op'] == 'add') {
        prev_item['from'] = prev_item['path'];
        prev_item['path'] = item['path'];
    } else {
        var parts = move_from.rsplit('/', 1);
        head = parts[0];
        move_from = parts[1];
        move_from = int(item['path']) - 1;
        prev_item['from'] = head + '/' + item['path'];
        prev_item['path'] = prev_item['path'];
    }
}

Upvotes: 5

neuront
neuront

Reputation: 9612

Split it into two steps.

First

print ['a', 'b'][0 == 1]
# 'a'
print ['a', 'b'][0 == 0]
# 'b'

In python, if you use a boolean value as array index, False is considered as 0, and True as 1. So in your case, the value of

[
    (item['path'], prev_item['path']),
    (prev_item['path'], item['path']),
][item['op'] == 'add']

should be (item['path'], prev_item['path']) if item['op'] is not "add" otherwise (prev_item['path'], item['path']).

Then the assignment

a, b = (0, 1)

is very similar to a = 0, b = 1. In your case, if item['op'] equals to "add", the result is

move_from = prev_item['path']
move_to = item['path']

Although it is completely valid to use a boolean value, I don't suggest program like that. A more common convention is to use CONSEQUENCE if PREDICATE else ALTERNATIVE (like PREDICATE ? CONSEQUENCE : ALTERNATIVE in C-like language)

 move_from, move_to = (prev_item['path'], item['path']) \
    if item['op'] == 'add' else \
    (item['path'], prev_item['path'])

Since there's no tuple assignment in JS, I think a simple way is

if (item['op'] === 'add') {
    move_from = prev_item['path'];
    move_to = item['path'];
} else {
    move_from = item['path'];
    move_to = prev_item['path'];
}

Upvotes: 3

ffledgling
ffledgling

Reputation: 12140

What you see here is a little trick pythonistas often use in code golf. Let break this code down.

move_from, move_to = [
        (item['path'], prev_item['path']),
        (prev_item['path'], item['path']),
    ][item['op'] == 'add']

First :

[item['op'] == 'add']

what this does is compares item['op'] to add.
This comparison then returns a Boolean value, i.e True or False
In python True and False are essentially equivalent to 1 and 0 respectively.

Now essentially we have:

move_from, move_to = [
                 (item['path'], prev_item['path']),
                 (prev_item['path'], item['path'])
          ][<0 or 1>]

Now depending on the whether the comparisons was true or false, the first or the second element of this array is returned.

In both cases the object returned (or selected from the array/list) is a tuple of the form: (a, b). Now Python does something called tuple unpacking.

So when you see:

move_from, move_to = (a, b)

it essentially means:

move_from = a

and

move_to = b

I hope that clarifies how this code works.

Upvotes: 0

Roberto
Roberto

Reputation: 2786

As sdolan said, the [item['op'] == 'add'] will select which of the two tuples will be used to refer move_from and move_to.

Try this simplification yourself, and switch [True] to [False] for comparison:

move_from, move_to = [(1, 2), (3, 4),][True]
print(move_from)
print(move_to)

Upvotes: 1

Related Questions