Python中的双重赋值
请查看代码 这里
move_from, move_to = [
(item['path'], prev_item['path']),
(prev_item['path'], item['path']),
][item['op'] == 'add']
这里的move_from和move_to被赋值了什么?看起来像是双重赋值,但右边没有看到两个(我不是Python程序员)。我想把它移植到JavaScript,应该怎么写呢?
谢谢。
4 个回答
这里你看到的是一些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中,True
和 False
分别相当于数字 1
和 0
。
所以我们实际上得到了:
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
希望这些解释能让你更清楚这段代码是怎么工作的。
正如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)
把这个过程分成两步。
第一步
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 = 0
,b = 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'];
}
[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'];
}
}