Python中的双重赋值

0 投票
4 回答
577 浏览
提问于 2025-04-18 02:54

请查看代码 这里

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

这里的move_from和move_to被赋值了什么?看起来像是双重赋值,但右边没有看到两个(我不是Python程序员)。我想把它移植到JavaScript,应该怎么写呢?

谢谢。

4 个回答

0

这里你看到的是一些Python程序员在写代码时常用的小技巧,特别是在代码比赛中。我们来逐步分析一下这段代码。

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

首先:

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

这段代码的作用是将 item['op']add 进行比较。
这个比较会返回一个布尔值,也就是 True(真)或 False(假)。
在Python中,TrueFalse 分别相当于数字 10

所以我们实际上得到了:

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

根据比较的结果是对还是错,会返回这个数组的第一个或第二个元素。

无论是哪种情况,返回的对象(或者说从数组/列表中选出来的)都是一个形式为 (a, b) 的元组。

接下来,Python会进行一种叫做 元组解包 的操作。

所以当你看到:

move_from, move_to = (a, b)

这实际上意味着:

move_from = a

而且

move_to = b

希望这些解释能让你更清楚这段代码是怎么工作的。

1

正如sdolan所说,[item['op'] == 'add'] 这个部分会决定使用哪一个元组来表示move_from和move_to。

你可以自己试试这个简化的过程,把[True]换成[False]来进行比较:

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

把这个过程分成两步。

第一步

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

在Python中,如果你用布尔值(也就是真或假)作为数组的索引,False会被当作0,而True会被当作1。所以在你的例子中,

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

应该是(item['path'], prev_item['path']),如果item['op']不是"add",否则就是(prev_item['path'], item['path'])

然后赋值的部分

a, b = (0, 1)

a = 0b = 1很相似。在你的例子中,如果item['op']等于"add",结果就是

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

虽然用布尔值来做是完全可以的,但我不建议这样编程。更常见的写法是用CONSEQUENCE if PREDICATE else ALTERNATIVE(就像在C语言中用PREDICATE ? CONSEQUENCE : ALTERNATIVE)。

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

由于在JavaScript中没有元组赋值,我觉得一个简单的方法是

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

这是一个 Python 列表。第一个(0)项是

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

而第二个(1)是

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

这里的布尔值

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

会评估为真或假(1 或 0),所以会选择其中一个项。

举个例子,如果 item['op'] 等于 'add',那么结果是

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

编辑:你问了关于 JS 代码的事。这段代码可能适合你。注意,我假设大部分变量是全局的,因为我不知道你会在什么环境下使用它。

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'];
    }
}

撰写回答