3

为什么下一条 python 行不是语法错误?如果真的不是,那么我该如何使用它以及在什么情况下它会有用?

 a= range(10)[1:3]=[2,3]
4

3 回答 3

6

Python 支持在同一行进行多个赋值:

>>> a = b = c = 2
>>> a
2
>>> b
2
>>> c
2

由于您将第一个分配给一个列表(python 中的一个可变对象),然后将该列表的一部分(它是可变的)和一个分配给第三个项目的内容,因此 python 可以接受。如果你用不可变的东西替换了你的中间值,你会得到一个错误。

>>> a = 'foo' = 'bar'
  File "<input>", line 1
SyntaxError: can't assign to literal

>>> a = {}['foo'] = 'bar'
>>> a
'bar'

有趣的是,这样的行仍然会引发错误,因为您试图将值 3 和 4 分配给字面值 1 和 2。

>>> a = [1, 2] = [3, 4]
  File "<input>", line 1
SyntaxError: can't assign to literal

虽然这不会:

>>> a = [1, 2][:] = [3, 4]
>>> a
[3, 4]

在这种情况下,关键是通过使用切片表示法,您将分配给列表内的范围,而不是重新分配给列表中的文字值。

此外,线条

>>> a = [[], []] = [{}, {}]
>>> a
[{}, {}]

>>> a = [b, c] = 3, 4
>>> b
3
>>> c
4

是有效的,第一个是因为内部列表和字典都是可变的和可迭代的,第二个是因为您将 3 和 4 分配给变量 b 和 c 而不是文字(感谢 Sven :D)。

编辑回答操作的最后一个问题。

>>> a = 1
>>> b = 2
>>> a,b = b,a = a,b
>>> a
2
>>> b
1

这只是归结为 b,a = a,b 的最终(最右边)分配。观察:

>>> a, b = 'a', 'b'
>>> a, b = b, a = a, b = b, a
>>> a
'b'
>>> b
'a'
>>> a, b = b, a = b, a
>>> a
'a'
>>> b
'b'

这令人困惑,但我对此的解释是在语句完成之前不会重新评估/分配新值 a 和 b,因此重要的分配是最右边的分配。如果最后一条语句是 a、b = a、b 或 b,a = b、a、a 和 b 的值不会改变。如果是a,b = b,a或b,a = a,b,则切换值。

于 2012-04-06T23:39:31.210 回答
2

好吧,让我们从 range 函数开始分解一下。range 函数创建一个从 0 到 9 的整数列表。所以你最终得到了这个

[0,1,2,3,4,5,6,7,8,9]

接下来,切片符号将应用于您的整数列表。在冒号之前指定一个数字告诉 python 你想用它作为你的起始索引,因为列表是零索引的,你得到列表中的第二个元素,即值 1。你还给了第二个值提供的数字一个附加索引,因此您将获得不超过该索引的值。但这只会导致第三个元素,它直接跟在起始索引值之后。现在你有了这个:

[1,2]

传统上,在编程语言中,值是从右到左分配的。范围/切片操作似乎在分配之前完成,因为最右边的列表替换了范围操作创建的值。然后将该值再次分配给a。

除非您绝对必须这样做,否则不要像这样重复分配。这是可怕的阅读和理解。最好有可读/更简单的代码。我从来没有用这种方式分配东西。老实说,甚至没有理由处理范围操作,因为它只是被替换了。这只是一个奇怪的东西,最好不要使用。国际海事组织。

于 2012-04-06T23:41:57.137 回答
2

这条线确实不是错误,但它从来没有用处。它的作用与

a = [2, 3]

此外,它创建一个包含内容的新列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],并将该列表的第二项和第三项设置为2and 3,最后再次删除该新列表,因为根本没有对它的引用。

这是一个更完整的代码。选择语句的顺序以匹配原始语句的执行顺序:

a = [2, 3]
b = range(10)
b[1:3] = a
del b
于 2012-04-06T23:35:18.903 回答