[] = (), () = (), and {} = () '赋值' [英] [] = (), () = (), and {} = () 'assignments'

查看:65
本文介绍了[] = (), () = (), and {} = () '赋值'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我惊讶地发现以下内容,在 Python 3 中,前两个没有引发任何问题:

<预><代码>>>>[] = ()>>>() = ()>>>{} = ()文件<stdin>",第 1 行语法错误:无法分配给文字

在 Python 2.7 中,只有第一个不会引发任何问题:

<预><代码>>>>[] = ()>>>() = ()文件<stdin>",第 1 行语法错误:不能分配给 ()>>>{} = ()文件<stdin>",第 1 行语法错误:无法分配给文字

这里发生了什么?为什么其中任何一个都不会引发错误?为什么 () = () 可能被添加为在 Python 3 中有效?

*注意,您可以用任何空的可迭代对象替换右侧(例如 [] = set()),我只是为插图选择了一个空元组

解决方案

根据 Issue23275,这些基本上是怪癖,不会造成真正的伤害,但也没有效用.注意 [] = () 不会改变 list 文字:

<预><代码>>>>[] = ()>>>类型([])<类'列表'>

[] = x 语句基本上断言 x 是可迭代的并且 x 是空的(尽管没有人会推荐使用它们方式),例如

<预><代码>>>>[] = (1)回溯(最近一次调用最后一次):文件<stdin>",第 1 行,位于 <module>类型错误:int"对象不可迭代>>>[] = (1,)回溯(最近一次调用最后一次):文件<stdin>",第 1 行,位于 <module>ValueError:解包的值太多

作为 John Y 的评论,最好考虑 [] = () 不是赋值,而是一种与 Python 的可迭代解包语法保持一致的方式.

正如 ArrowCase 注释,此语法也扩展到多个赋值:

<预><代码>>>>a = [] = ()>>>一种()

查看多重赋值的 CPython 字节码说明此操作类似于普通的可迭代解包语法,使用 UNPACK_SEQUENCE 指令:

<预><代码>>>>dis.dis('a = [] = ()')1 0 BUILD_TUPLE 02 DUP_TOP4 STORE_NAME 0 (a)6 解包_序列 08 LOAD_CONST 0(无)10 RETURN_VALUE>>>dis.dis('[a, b] = (1, 2)')1 0 LOAD_CONST 3 ((1, 2))2 解包_序列 24 STORE_NAME 0 (a)6 STORE_NAME 1 (b)8 LOAD_CONST 2(无)10 RETURN_VALUE

同样的 Issue23275 指出 () = () 已作为有效语法添加到 Python 3 中以保持一致性.决定删除 [] = () 会不必要地破坏代码,因为它不会造成伤害并且符合可迭代的解包逻辑.{} = () 仍然无效,因为解包语法在带大括号的上下文中没有意义.

如果有人想知道,像 list() = () 这样的语法在语法上是无效的,因为你永远不能分配给函数调用.

I was surprised to find the following, in Python 3, the first two raise nothing:

>>> [] = ()
>>> () = ()
>>> {} = ()
  File "<stdin>", line 1
SyntaxError: can't assign to literal

In Python 2.7, only the first one raises nothing:

>>> [] = ()
>>> () = ()
  File "<stdin>", line 1
SyntaxError: can't assign to ()
>>> {} = ()
  File "<stdin>", line 1
SyntaxError: can't assign to literal

What is going on here? Why are any of then not raising errors? And why was the () = () presumably added to be valid in Python 3?

*Note, you can replace the right hand side with any empty iterable (e.g. [] = set()), I just choose an empty tuple for the illustration

解决方案

According to Issue23275, these are basically quirks causing no real harm but also no utility. Note that [] = () does not alter the list literal:

>>> [] = ()
>>> type([])
<class 'list'>

[] = x statements basically assert that x is iterable and that x is empty (although no-one would recommend using them this way), e.g.

>>> [] = (1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
>>> [] = (1,)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack

As John Y comments it is best to think of [] = () as not an assignment but a way of being consistent with Python's iterable unpacking syntax.

As ArrowCase comments, this syntax also extends to multiple assignments:

>>> a = [] = ()
>>> a
()

Looking at the CPython bytecode of the multiple assignment illustrates that this operations are similar to the normal iterable unpacking syntax, using the UNPACK_SEQUENCE instruction:

>>> dis.dis('a = [] = ()')
  1           0 BUILD_TUPLE              0
              2 DUP_TOP
              4 STORE_NAME               0 (a)
              6 UNPACK_SEQUENCE          0
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE
>>> dis.dis('[a, b] = (1, 2)')
  1           0 LOAD_CONST               3 ((1, 2))
              2 UNPACK_SEQUENCE          2
              4 STORE_NAME               0 (a)
              6 STORE_NAME               1 (b)
              8 LOAD_CONST               2 (None)
             10 RETURN_VALUE

The same Issue23275 states that () = () was added as valid syntax to Python 3 for concordance. It was decided that removing [] = () would break code needlessly, since it causes no harm and fits with iterable unpacking logic. {} = () is still invalid because the unpacking syntax does not make sense in this context with braces.

In case anyone is wondering, syntax like list() = () is simply syntactically invalid, because you can never assign to function call.

这篇关于[] = (), () = (), and {} = () '赋值'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆