解包、扩展解包和嵌套扩展解包 [英] Unpacking, extended unpacking and nested extended unpacking

查看:64
本文介绍了解包、扩展解包和嵌套扩展解包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下表达式.请注意,某些表达式被重复以呈现上下文".

Consider the following expressions. Note that some expressions are repeated to present the "context".

(这是一个很长的列表)

(this is a long list)

a, b = 1, 2                          # simple sequence assignment
a, b = ['green', 'blue']             # list asqignment
a, b = 'XY'                          # string assignment
a, b = range(1,5,2)                  # any iterable will do


                                     # nested sequence assignment

(a,b), c = "XY", "Z"                 # a = 'X', b = 'Y', c = 'Z' 

(a,b), c = "XYZ"                     # ERROR -- too many values to unpack
(a,b), c = "XY"                      # ERROR -- need more than 1 value to unpack

(a,b), c, = [1,2],'this'             # a = '1', b = '2', c = 'this'
(a,b), (c,) = [1,2],'this'           # ERROR -- too many values to unpack


                                     # extended sequence unpacking

a, *b = 1,2,3,4,5                    # a = 1, b = [2,3,4,5]
*a, b = 1,2,3,4,5                    # a = [1,2,3,4], b = 5
a, *b, c = 1,2,3,4,5                 # a = 1, b = [2,3,4], c = 5

a, *b = 'X'                          # a = 'X', b = []
*a, b = 'X'                          # a = [], b = 'X'
a, *b, c = "XY"                      # a = 'X', b = [], c = 'Y'
a, *b, c = "X...Y"                   # a = 'X', b = ['.','.','.'], c = 'Y'

a, b, *c = 1,2,3                     # a = 1, b = 2, c = [3]
a, b, c, *d = 1,2,3                  # a = 1, b = 2, c = 3, d = []

a, *b, c, *d = 1,2,3,4,5             # ERROR -- two starred expressions in assignment

(a,b), c = [1,2],'this'              # a = '1', b = '2', c = 'this'
(a,b), *c = [1,2],'this'             # a = '1', b = '2', c = ['this']

(a,b), c, *d = [1,2],'this'          # a = '1', b = '2', c = 'this', d = []
(a,b), *c, d = [1,2],'this'          # a = '1', b = '2', c = [], d = 'this'

(a,b), (c, *d) = [1,2],'this'        # a = '1', b = '2', c = 't', d = ['h', 'i', 's']

*a = 1                               # ERROR -- target must be in a list or tuple
*a = (1,2)                           # ERROR -- target must be in a list or tuple
*a, = (1,2)                          # a = [1,2]
*a, = 1                              # ERROR -- 'int' object is not iterable
*a, = [1]                            # a = [1]
*a = [1]                             # ERROR -- target must be in a list or tuple
*a, = (1,)                           # a = [1]
*a, = (1)                            # ERROR -- 'int' object is not iterable

*a, b = [1]                          # a = [], b = 1
*a, b = (1,)                         # a = [], b = 1

(a,b),c = 1,2,3                      # ERROR -- too many values to unpack
(a,b), *c = 1,2,3                    # ERROR - 'int' object is not iterable
(a,b), *c = 'XY', 2, 3               # a = 'X', b = 'Y', c = [2,3]


                                     # extended sequence unpacking -- NESTED

(a,b),c = 1,2,3                      # ERROR -- too many values to unpack
*(a,b), c = 1,2,3                    # a = 1, b = 2, c = 3

*(a,b) = 1,2                         # ERROR -- target must be in a list or tuple
*(a,b), = 1,2                        # a = 1, b = 2

*(a,b) = 'XY'                        # ERROR -- target must be in a list or tuple
*(a,b), = 'XY'                       # a = 'X', b = 'Y'

*(a, b) = 'this'                     # ERROR -- target must be in a list or tuple
*(a, b), = 'this'                    # ERROR -- too many values to unpack
*(a, *b), = 'this'                   # a = 't', b = ['h', 'i', 's']

*(a, *b), c = 'this'                 # a = 't', b = ['h', 'i'], c = 's'

*(a,*b), = 1,2,3,3,4,5,6,7           # a = 1, b = [2, 3, 3, 4, 5, 6, 7]

*(a,*b), *c = 1,2,3,3,4,5,6,7        # ERROR -- two starred expressions in assignment
*(a,*b), (*c,) = 1,2,3,3,4,5,6,7     # ERROR -- 'int' object is not iterable
*(a,*b), c = 1,2,3,3,4,5,6,7         # a = 1, b = [2, 3, 3, 4, 5, 6], c = 7
*(a,*b), (*c,) = 1,2,3,4,5,'XY'      # a = 1, b = [2, 3, 4, 5], c = ['X', 'Y']

*(a,*b), c, d = 1,2,3,3,4,5,6,7      # a = 1, b = [2, 3, 3, 4, 5], c = 6, d = 7
*(a,*b), (c, d) = 1,2,3,3,4,5,6,7    # ERROR -- 'int' object is not iterable
*(a,*b), (*c, d) = 1,2,3,3,4,5,6,7   # ERROR -- 'int' object is not iterable
*(a,*b), *(c, d) = 1,2,3,3,4,5,6,7   # ERROR -- two starred expressions in assignment


*(a,b), c = 'XY', 3                  # ERROR -- need more than 1 value to unpack
*(*a,b), c = 'XY', 3                 # a = [], b = 'XY', c = 3
(a,b), c = 'XY', 3                   # a = 'X', b = 'Y', c = 3

*(a,b), c = 'XY', 3, 4               # a = 'XY', b = 3, c = 4
*(*a,b), c = 'XY', 3, 4              # a = ['XY'], b = 3, c = 4
(a,b), c = 'XY', 3, 4                # ERROR -- too many values to unpack

如何手动正确推导出此类表达式的结果?

How to correctly deduce the result of such expressions by hand?

推荐答案

对于这篇文章的篇幅我深表歉意,但我决定选择完整性.

My apologies for the length of this post, but I decided to opt for completeness.

一旦您了解了一些基本规则,就不难概括它们.我会尽力用几个例子来解释.由于您正在谈论手动"评估这些,我将建议一些简单的替换规则.基本上,如果所有可迭代对象的格式都相同,您可能会发现更容易理解表达式.

Once you know a few basic rules, it's not hard to generalize them. I'll do my best to explain with a few examples. Since you're talking about evaluating these "by hand," I'll suggest some simple substitution rules. Basically, you might find it easier to understand an expression if all the iterables are formatted in the same way.

仅出于解包的目的,以下替换在 = 的右侧有效(即对于 rvalues):

For the purposes of unpacking only, the following substitutions are valid on the right side of the = (i.e. for rvalues):

'XY' -> ('X', 'Y')
['X', 'Y'] -> ('X', 'Y')

如果您发现一个值没有被解包,那么您将撤消替换.(有关进一步说明,请参见下文.)

If you find that a value doesn't get unpacked, then you'll undo the substitution. (See below for further explanation.)

此外,当您看到裸"逗号时,请假装有一个顶级元组.在左侧和右侧执行此操作(即对于 lvaluesrvalues):

Also, when you see "naked" commas, pretend there's a top-level tuple. Do this on both the left and the right side (i.e. for lvalues and rvalues):

'X', 'Y' -> ('X', 'Y')
a, b -> (a, b)

考虑到这些简单的规则,以下是一些示例:

With those simple rules in mind, here are some examples:

(a,b), c = "XY", "Z"                 # a = 'X', b = 'Y', c = 'Z'

应用以上规则,我们将"XY"转换为('X', 'Y'),并覆盖括号中的裸逗号:

Applying the above rules, we convert "XY" to ('X', 'Y'), and cover the naked commas in parens:

((a, b), c) = (('X', 'Y'), 'Z')

这里的视觉对应使得分配的工作方式非常明显.

The visual correspondence here makes it fairly obvious how the assignment works.

这是一个错误的例子:

(a,b), c = "XYZ"

按照上述替换规则,我们得到以下内容:

Following the above substitution rules, we get the below:

((a, b), c) = ('X', 'Y', 'Z')

这显然是错误的;嵌套结构不匹配.现在让我们看看它是如何处理一个稍微复杂的例子的:

This is clearly erroneous; the nested structures don't match up. Now let's see how it works for a slightly more complex example:

(a,b), c, = [1,2],'this'             # a = '1', b = '2', c = 'this'

应用以上规则,我们得到

Applying the above rules, we get

((a, b), c) = ((1, 2), ('t', 'h', 'i', 's'))

但是现在从结构上可以清楚地看出'this'不会被解包,而是直接赋值给c.所以我们撤消了替换.

But now it's clear from the structure that 'this' won't be unpacked, but assigned directly to c. So we undo the substitution.

((a, b), c) = ((1, 2), 'this')

现在让我们看看当我们将 c 包装在一个元组中时会发生什么:

Now let's see what happens when we wrap c in a tuple:

(a,b), (c,) = [1,2],'this'           # ERROR -- too many values to unpack

成为

((a, b), (c,)) = ((1, 2), ('t', 'h', 'i', 's'))

同样,错误很明显.c 不再是一个裸变量,而是一个序列内部的变量,所以右边对应的序列被解包成(c,).但是序列有不同的长度,所以有一个错误.

Again, the error is obvious. c is no longer a naked variable, but a variable inside a sequence, and so the corresponding sequence on the right is unpacked into (c,). But the sequences have a different length, so there's an error.

现在使用 * 操作符进行扩展解包.这有点复杂,但它仍然相当简单.* 前面的变量成为一个列表,其中包含相应序列中未分配给变量名称的任何项目.从一个相当简单的例子开始:

Now for extended unpacking using the * operator. This is a bit more complex, but it's still fairly straightforward. A variable preceded by * becomes a list, which contains any items from the corresponding sequence that aren't assigned to variable names. Starting with a fairly simple example:

a, *b, c = "X...Y"                   # a = 'X', b = ['.','.','.'], c = 'Y'

这就变成了

(a, *b, c) = ('X', '.', '.', '.', 'Y')

分析这个最简单的方法是从两端开始工作.'X' 分配给 a'Y' 分配给 c.序列中剩余的值放在一个列表中并分配给 b.

The simplest way to analyze this is to work from the ends. 'X' is assigned to a and 'Y' is assigned to c. The remaining values in the sequence are put in a list and assigned to b.

(*a, b)(a, *b) 这样的左值只是上述情况的特例.在一个左值序列中不能有两个 * 运算符,因为它会产生歧义.像这样 (a, *b, *c, d) -- 在 bc 中的值会在哪里?稍后我将考虑嵌套的情况.

Lvalues like (*a, b) and (a, *b) are just special cases of the above. You can't have two * operators inside one lvalue sequence because it would be ambiguous. Where would the values go in something like this (a, *b, *c, d) -- in b or c? I'll consider the nested case in a moment.

*a = 1                               # ERROR -- target must be in a list or tuple

这里的错误是不言自明的.目标 (*a) 必须在元组中.

Here the error is fairly self-explanatory. The target (*a) must be in a tuple.

*a, = (1,2)                          # a = [1,2]

这是有效的,因为有一个裸逗号.应用规则...

This works because there's a naked comma. Applying the rules...

(*a,) = (1, 2)

由于除了 *a 之外没有任何变量,*a 将右值序列中的所有值都吸起来.如果将 (1, 2) 替换为单个值会怎样?

Since there are no variables other than *a, *a slurps up all the values in the rvalue sequence. What if you replace the (1, 2) with a single value?

*a, = 1                              # ERROR -- 'int' object is not iterable

变成

(*a,) = 1

同样,这里的错误是不言自明的.你不能解压一些不是序列的东西,而 *a 需要一些东西来解压.所以我们把它放在一个序列中

Again, the error here is self-explanatory. You can't unpack something that isn't a sequence, and *a needs something to unpack. So we put it in a sequence

*a, = [1]                            # a = [1]

相当于

(*a,) = (1,)

最后,这是一个常见的混淆点:(1)1 相同——您需要一个逗号来区分元组和算术语句.

Finally, this is a common point of confusion: (1) is the same as 1 -- you need a comma to distinguish a tuple from an arithmetic statement.

*a, = (1)                            # ERROR -- 'int' object is not 

现在进行嵌套.实际上这个例子不在你的NESTED"部分;也许你没有意识到它是嵌套的?

Now for nesting. Actually this example wasn't in your "NESTED" section; perhaps you didn't realize it was nested?

(a,b), *c = 'XY', 2, 3               # a = 'X', b = 'Y', c = [2,3]

成为

((a, b), *c) = (('X', 'Y'), 2, 3)

顶层元组中的第一个值被赋值,顶层元组中剩余的值(23)被赋值给c——正如我们所期望的那样.

The first value in the top-level tuple gets assigned, and the remaining values in the top-level tuple (2 and 3) are assigned to c -- just as we should expect.

(a,b),c = 1,2,3                      # ERROR -- too many values to unpack
*(a,b), c = 1,2,3                    # a = 1, b = 2, c = 3

我已经在上面解释了为什么第一行会抛出错误.第二行很愚蠢,但这就是它起作用的原因:

I've already explained above why the first line throws an error. The second line is silly but here's why it works:

(*(a, b), c) = (1, 2, 3)

如前所述,我们从头开始工作.3 分配给 c,然后将剩余的值分配给前面带有 * 的变量,在本例中为 (a, b).所以这等价于 (a, b) = (1, 2) ,因为有正确数量的元素,所以它恰好有效.我想不出任何原因会出现在工作代码中.同样,

As previously explained, we work from the ends. 3 is assigned to c, and then the remaining values are assigned to the variable with the * preceding it, in this case, (a, b). So that's equivalent to (a, b) = (1, 2), which happens to work because there are the right number of elements. I can't think of any reason this would ever appear in working code. Similarly,

*(a, *b), c = 'this'                 # a = 't', b = ['h', 'i'], c = 's'

变成

(*(a, *b), c) = ('t', 'h', 'i', 's')

从头开始,'s'被赋值给c,而('t', 'h', 'i') 分配给 (a, *b).再次从末端开始,'t' 被分配给 a,而 ('h', 'i') 被分配给 b 作为一个列表.这是另一个不应出现在工作代码中的愚蠢示例.

Working from the ends, 's' is assigned to c, and ('t', 'h', 'i') is assigned to (a, *b). Working again from the ends, 't' is assigned to a, and ('h', 'i') is assigned to b as a list. This is another silly example that should never appear in working code.

这篇关于解包、扩展解包和嵌套扩展解包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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