标签归档:iterable-unpacking

开箱,扩展开箱和嵌套扩展开箱

问题:开箱,扩展开箱和嵌套扩展开箱

请考虑以下表达式。注意,某些表达被重复以表示“上下文”。

(这是一长串)

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

如何手工正确地推论这些表达式的结果?

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?


回答 0

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

一旦您了解了一些基本规则,就可以将它们概括起来。我将尽力举例说明。由于您是在谈论“手工”评估,因此,我将建议一些简单的替换规则。基本上,如果所有可迭代对象的格式都相同,则可能会更容易理解表达式。

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

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

如果发现值没有解包,则将撤消替换。(有关更多说明,请参见下文。)

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

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

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

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

应用上述规则,我们将转换"XY"('X', 'Y'),并用括号括住裸逗号:

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

这里的视觉对应关系使分配工作原理非常明显。

这是一个错误的示例:

(a,b), c = "XYZ"

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

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

这显然是错误的;嵌套结构不匹配。现在,让我们来看一个稍微复杂的示例的工作方式:

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

应用上述规则,我们得到

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

但是现在从结构上很明显,它'this'不会被解包,而是直接分配给c。因此,我们撤消替换。

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

现在,让我们看一下在包装c元组时会发生什么:

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

成为

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

同样,该错误是显而易见的。c不再是裸变量,而是序列内的变量,因此右侧的相应序列被解包为(c,)。但是序列的长度不同,因此会出现错误。

现在使用*操作员扩展拆箱。这有点复杂,但仍然相当简单。*开头的变量将成为一个列表,其中包含相应序列中未分配给变量名称的所有项目。从一个非常简单的示例开始:

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

这变成

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

分析此问题的最简单方法是从头开始工作。'X'被分配给a'Y'分配给c。序列中的其余值将放入列表中并分配给b

Lvalue像(*a, b)(a, *b)只是上述情况的特例。*一个左值序列内不能有两个运算符,因为这会造成歧义。该值会去哪里在这样的事情(a, *b, *c, d)-在bc?一会儿我将考虑嵌套案例。

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

这里的错误是不言自明的。目标(*a)必须位于一个元组中。

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

这是有效的,因为有一个赤裸的逗号。正在应用规则…

(*a,) = (1, 2)

由于除以外没有其他变量*a*a所以将rvalue序列中的所有值都吸收掉。如果(1, 2)用单个值替换,该怎么办?

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

变成

(*a,) = 1

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

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

相当于

(*a,) = (1,)

最后,这是一个常见的混淆点:(1)1– 一样,您需要使用逗号将元组与算术语句区分开。

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

现在进行嵌套。实际上,此示例不在您的“嵌套”部分中;也许您没有意识到它是嵌套的?

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

成为

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

就像我们所期望的那样,顶级元组中的第一个值被分配,而顶级元组(23)中的其余值被分配给c

(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), c) = (1, 2, 3)

如前所述,我们从头开始。3被分配给c,然后将剩余的值被分配给具有可变*它前面,在这种情况下,(a, b)。因此,这等效于(a, b) = (1, 2),由于元素数量正确,因此碰巧可以使用。我不认为这会在工作代码中出现任何原因。同样,

*(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作为列表。这是另一个愚蠢的示例,永远不要出现在工作代码中。

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.

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.)

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'

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.

Here’s an erroneous example:

(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'))

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')

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

Becomes

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

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'

This becomes

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

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.

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

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)

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

becomes

(*a,) = 1

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]

Which is eqivalent to

(*a,) = (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 

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]

Becomes

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

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)

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'

becomes

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

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.


回答 1

我发现解压缩Python 2元组非常简单。左侧的每个名称都与整个序列或右侧序列中的单个项目相对应。如果名称对应于任何序列的单个项目,则必须有足够的名称来覆盖所有项目。

但是,扩展解压缩肯定会造成混乱,因为它是如此强大。现实情况是,您永远不应该再执行给出的最后10个或更多有效的示例-如果数据是结构化的,则应使用dict类或类实例,而不是列表等非结构化形式。

显然,新语法可能会被滥用。您的问题的答案是,您不必阅读这样的表达式-它们是一种不好的做法,我怀疑它们会被使用。

仅仅因为您可以编写任意复杂的表达式并不意味着您应该这样做。您可以像这样编写代码,map(map, iterable_of_transformations, map(map, iterable_of_transformations, iterable_of_iterables_of_iterables))但不能这样

I find the Python 2 tuple unpacking pretty straightforward. Each name on the left corresponds with either an entire sequence or a single item in a sequence on the right. If names correspond to single items of any sequence, then there must be enough names to cover all of the items.

Extended unpacking, however, can certainly be confusing, because it is so powerful. The reality is you should never be doing the last 10 or more valid examples you gave — if the data is that structured, it should be in a dict or a class instance, not unstructured forms like lists.

Clearly, the new syntax can be abused. The answer to your question is that you shouldn’t have to read expressions like that — they’re bad practice and I doubt they’ll be used.

Just because you can write arbitrarily complex expressions doesn’t mean you should. You could write code like map(map, iterable_of_transformations, map(map, iterable_of_transformations, iterable_of_iterables_of_iterables)) but you don’t.


回答 2

我认为您的代码可能会产生误导,请使用其他形式来表达它。

这就像在表达式中使用多余的括号来避免有关运算符优先级的问题。为了使您的代码易于阅读,我总是不花钱。

我更喜欢仅将拆包用于交换之类的简单任务。

I you think your code may be misleading use other form to express it.

It’s like using extra brackets in expressions to avoid questions about operators precedence. I’ts always a good investment to make your code readable.

I prefer to use unpacking only for simple tasks like swap.


如何将字典转换为元组列表?

问题:如何将字典转换为元组列表?

如果我有这样的字典:

{ 'a': 1, 'b': 2, 'c': 3 }

如何将其转换为此?

[ ('a', 1), ('b', 2), ('c', 3) ]

以及如何将其转换为此?

[ (1, 'a'), (2, 'b'), (3, 'c') ]

If I have a dictionary like:

{ 'a': 1, 'b': 2, 'c': 3 }

How can I convert it to this?

[ ('a', 1), ('b', 2), ('c', 3) ]

And how can I convert it to this?

[ (1, 'a'), (2, 'b'), (3, 'c') ]

回答 0

>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> d.items()
[('a', 1), ('c', 3), ('b', 2)]
>>> [(v, k) for k, v in d.iteritems()]
[(1, 'a'), (3, 'c'), (2, 'b')]

它不是您想要的顺序,但是字典始终没有任何特定的顺序。1对其进行排序或根据需要进行组织。

参见:items()iteritems()


在Python 3.x中,您将不使用iteritems(不再存在),而使用items,它现在返回字典项目的“视图”。看到什么新的Python 3.0文档,以及新的看法文档

1:在Python 3.7中添加了字典的插入顺序保留

>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> d.items()
[('a', 1), ('c', 3), ('b', 2)]
>>> [(v, k) for k, v in d.iteritems()]
[(1, 'a'), (3, 'c'), (2, 'b')]

It’s not in the order you want, but dicts don’t have any specific order anyway.1 Sort it or organize it as necessary.

See: items(), iteritems()


In Python 3.x, you would not use iteritems (which no longer exists), but instead use items, which now returns a “view” into the dictionary items. See the What’s New document for Python 3.0, and the new documentation on views.

1: Insertion-order preservation for dicts was added in Python 3.7


回答 1

因为没有其他人做过,所以我将添加py3k版本:

>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> list(d.items())
[('a', 1), ('c', 3), ('b', 2)]
>>> [(v, k) for k, v in d.items()]
[(1, 'a'), (3, 'c'), (2, 'b')]

since no one else did, I’ll add py3k versions:

>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> list(d.items())
[('a', 1), ('c', 3), ('b', 2)]
>>> [(v, k) for k, v in d.items()]
[(1, 'a'), (3, 'c'), (2, 'b')]

回答 2

您可以使用列表推导。

[(k,v) for k,v in a.iteritems()] 

会得到你[ ('a', 1), ('b', 2), ('c', 3) ]

[(v,k) for k,v in a.iteritems()] 

另一个例子。

如果愿意,请阅读有关列表理解的更多信息,您可以使用它们来做非常有趣。

You can use list comprehensions.

[(k,v) for k,v in a.iteritems()] 

will get you [ ('a', 1), ('b', 2), ('c', 3) ] and

[(v,k) for k,v in a.iteritems()] 

the other example.

Read more about list comprehensions if you like, it’s very interesting what you can do with them.


回答 3

创建一个namedtuple列表

使用namedtuple通常很方便。例如,您有一个“名称”作为键,而“分数”作为值的字典,例如:

d = {'John':5, 'Alex':10, 'Richard': 7}

您可以将项目列为元组,根据需要进行排序,并获得名称和分数,比如说Python得分最高(index = 0)的玩家非常Python化,如下所示:

>>> player = best[0]

>>> player.name
        'Alex'
>>> player.score
         10

这该怎么做:

以随机顺序或保持collections.OrderedDict的顺序列出:

import collections
Player = collections.namedtuple('Player', 'name score')
players = list(Player(*item) for item in d.items())

按值(“分数”)排序:

import collections
Player = collections.namedtuple('Player', 'score name')

首先以最低分数排序:

worst = sorted(Player(v,k) for (k,v) in d.items())

首先以最高分排序:

best = sorted([Player(v,k) for (k,v) in d.items()], reverse=True)

Create a list of namedtuples

It can often be very handy to use namedtuple. For example, you have a dictionary of ‘name’ as keys and ‘score’ as values like:

d = {'John':5, 'Alex':10, 'Richard': 7}

You can list the items as tuples, sorted if you like, and get the name and score of, let’s say the player with the highest score (index=0) very Pythonically like this:

>>> player = best[0]

>>> player.name
        'Alex'
>>> player.score
         10

How to do this:

list in random order or keeping order of collections.OrderedDict:

import collections
Player = collections.namedtuple('Player', 'name score')
players = list(Player(*item) for item in d.items())

in order, sorted by value (‘score’):

import collections
Player = collections.namedtuple('Player', 'score name')

sorted with lowest score first:

worst = sorted(Player(v,k) for (k,v) in d.items())

sorted with highest score first:

best = sorted([Player(v,k) for (k,v) in d.items()], reverse=True)

回答 4

你想要的是dictitems()iteritems()方法。items返回(键,值)元组的列表。由于元组是不可变的,因此它们不能反转。因此,您必须迭代这些项并创建新的元组,以获取反转的(值,键)元组。对于迭代而言,iteritems是首选方法,因为它使用生成器来生成(键,值)元组,而不必将整个列表保留在内存中。

Python 2.5.1 (r251:54863, Jan 13 2009, 10:26:13) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = { 'a': 1, 'b': 2, 'c': 3 }
>>> a.items()
[('a', 1), ('c', 3), ('b', 2)]
>>> [(v,k) for (k,v) in a.iteritems()]
[(1, 'a'), (3, 'c'), (2, 'b')]
>>> 

What you want is dict‘s items() and iteritems() methods. items returns a list of (key,value) tuples. Since tuples are immutable, they can’t be reversed. Thus, you have to iterate the items and create new tuples to get the reversed (value,key) tuples. For iteration, iteritems is preferable since it uses a generator to produce the (key,value) tuples rather than having to keep the entire list in memory.

Python 2.5.1 (r251:54863, Jan 13 2009, 10:26:13) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = { 'a': 1, 'b': 2, 'c': 3 }
>>> a.items()
[('a', 1), ('c', 3), ('b', 2)]
>>> [(v,k) for (k,v) in a.iteritems()]
[(1, 'a'), (3, 'c'), (2, 'b')]
>>> 

回答 5

[(k,v) for (k,v) in d.iteritems()]

[(v,k) for (k,v) in d.iteritems()]
[(k,v) for (k,v) in d.iteritems()]

and

[(v,k) for (k,v) in d.iteritems()]

回答 6

这些是Python 3.x和Python 2.x的重大变化

对于Python3.x使用

dictlist = []
for key, value in dict.items():
    temp = [key,value]
    dictlist.append(temp)

对于Python 2.7使用

dictlist = []
for key, value in dict.iteritems():
    temp = [key,value]
    dictlist.append(temp)

These are the breaking changes from Python 3.x and Python 2.x

For Python3.x use

dictlist = []
for key, value in dict.items():
    temp = [key,value]
    dictlist.append(temp)

For Python 2.7 use

dictlist = []
for key, value in dict.iteritems():
    temp = [key,value]
    dictlist.append(temp)

回答 7

>>> a = {'a':1,'b':2,'c':3}

>>> [[x,a [x])for a.keys()中的x]
[('a',1),('c',3),('b',2)]

>>> [[(a [x],x)for a.keys()中的x]
[(1,'a'),(3,'c'),(2,'b')]
>>> a={ 'a': 1, 'b': 2, 'c': 3 }

>>> [(x,a[x]) for x in a.keys() ]
[('a', 1), ('c', 3), ('b', 2)]

>>> [(a[x],x) for x in a.keys() ]
[(1, 'a'), (3, 'c'), (2, 'b')]

回答 8

通过keys()values()字典的方法和zip

zip 将返回一个类似于有序字典的元组列表。

演示:

>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> zip(d.keys(), d.values())
[('a', 1), ('c', 3), ('b', 2)]
>>> zip(d.values(), d.keys())
[(1, 'a'), (3, 'c'), (2, 'b')]

By keys() and values() methods of dictionary and zip.

zip will return a list of tuples which acts like an ordered dictionary.

Demo:

>>> d = { 'a': 1, 'b': 2, 'c': 3 }
>>> zip(d.keys(), d.values())
[('a', 1), ('c', 3), ('b', 2)]
>>> zip(d.values(), d.keys())
[(1, 'a'), (3, 'c'), (2, 'b')]

回答 9

d = {'John':5, 'Alex':10, 'Richard': 7}
list = []
for i in d:
   k = (i,d[i])
   list.append(k)

print list
d = {'John':5, 'Alex':10, 'Richard': 7}
list = []
for i in d:
   k = (i,d[i])
   list.append(k)

print list

回答 10

一个简单的是

list(dictionary.items())  # list of (key, value) tuples
list(zip(dictionary.values(), dictionary.keys()))  # list of (key, value) tuples

第二个不是更简单,而是。

A simpler one would be

list(dictionary.items())  # list of (key, value) tuples
list(zip(dictionary.values(), dictionary.keys()))  # list of (key, value) tuples

在函数调用中,星号运算符是什么意思?

问题:在函数调用中,星号运算符是什么意思?

*运算符在Python中是什么意思,例如likezip(*x)或代码f(**k)

  1. 在解释器内部如何处理?
  2. 它会影响性能吗?是快还是慢?
  3. 什么时候有用,什么时候没有?
  4. 应该在函数声明中还是在调用中使用它?

What does the * operator mean in Python, such as in code like zip(*x) or f(**k)?

  1. How is it handled internally in the interpreter?
  2. Does it affect performance at all? Is it fast or slow?
  3. When is it useful and when is it not?
  4. Should it be used in a function declaration or in a call?

回答 0

单颗星*将序列/集合解压缩为位置参数,因此您可以执行以下操作:

def sum(a, b):
    return a + b

values = (1, 2)

s = sum(*values)

这将打开元组的包装,使其实际执行为:

s = sum(1, 2)

双星**只使用字典并因此命名参数来做同样的事情:

values = { 'a': 1, 'b': 2 }
s = sum(**values)

您还可以结合:

def sum(a, b, c, d):
    return a + b + c + d

values1 = (1, 2)
values2 = { 'c': 10, 'd': 15 }
s = sum(*values1, **values2)

将执行为:

s = sum(1, 2, c=10, d=15)

另请参见Python文档的4.7.4-解包参数列表


另外,您可以定义要接受的函数*x**y参数,这使函数可以接受在声明中未专门命名的任何数量的位置和/或命名参数。

例:

def sum(*values):
    s = 0
    for v in values:
        s = s + v
    return s

s = sum(1, 2, 3, 4, 5)

或搭配**

def get_a(**values):
    return values['a']

s = get_a(a=1, b=2)      # returns 1

这可以使您无需声明它们即可指定大量可选参数。

再一次,您可以结合:

def sum(*values, **options):
    s = 0
    for i in values:
        s = s + i
    if "neg" in options:
        if options["neg"]:
            s = -s
    return s

s = sum(1, 2, 3, 4, 5)            # returns 15
s = sum(1, 2, 3, 4, 5, neg=True)  # returns -15
s = sum(1, 2, 3, 4, 5, neg=False) # returns 15

The single star * unpacks the sequence/collection into positional arguments, so you can do this:

def sum(a, b):
    return a + b

values = (1, 2)

s = sum(*values)

This will unpack the tuple so that it actually executes as:

s = sum(1, 2)

The double star ** does the same, only using a dictionary and thus named arguments:

values = { 'a': 1, 'b': 2 }
s = sum(**values)

You can also combine:

def sum(a, b, c, d):
    return a + b + c + d

values1 = (1, 2)
values2 = { 'c': 10, 'd': 15 }
s = sum(*values1, **values2)

will execute as:

s = sum(1, 2, c=10, d=15)

Also see section 4.7.4 – Unpacking Argument Lists of the Python documentation.


Additionally you can define functions to take *x and **y arguments, this allows a function to accept any number of positional and/or named arguments that aren’t specifically named in the declaration.

Example:

def sum(*values):
    s = 0
    for v in values:
        s = s + v
    return s

s = sum(1, 2, 3, 4, 5)

or with **:

def get_a(**values):
    return values['a']

s = get_a(a=1, b=2)      # returns 1

this can allow you to specify a large number of optional parameters without having to declare them.

And again, you can combine:

def sum(*values, **options):
    s = 0
    for i in values:
        s = s + i
    if "neg" in options:
        if options["neg"]:
            s = -s
    return s

s = sum(1, 2, 3, 4, 5)            # returns 15
s = sum(1, 2, 3, 4, 5, neg=True)  # returns -15
s = sum(1, 2, 3, 4, 5, neg=False) # returns 15

回答 1

一点:这些不是运算符。表达式中使用运算符从现有值创建新值(例如1 + 2变为3。这里的*和**是函数声明和调用语法的一部分。

One small point: these are not operators. Operators are used in expressions to create new values from existing values (1+2 becomes 3, for example. The * and ** here are part of the syntax of function declarations and calls.


回答 2

对于要“存储”函数调用的情况,我发现这特别有用。

例如,假设我对功能“ add”进行了一些单元测试:

def add(a, b): return a + b
tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
for test, result in tests.items():
   print 'test: adding', test, '==', result, '---', add(*test) == result

除了手动执行类似add(test [0],test [1])之类的丑陋操作外,没有其他方法可以调用add。另外,如果变量数量可变,则所有需要的if语句的代码都会变得很丑陋。

另一个有用的地方是定义Factory对象(为您创建对象的对象)。假设您有一些工厂类,该类使Car对象返回。您可以使myFactory.make_car(’red’,’bmw’,’335ix’)创建Car(’red’,’bmw’,’335ix’),然后返回它。

def make_car(*args):
   return Car(*args)

当您要调用超类的构造函数时,这也很有用。

I find this particularly useful for when you want to ‘store’ a function call.

For example, suppose I have some unit tests for a function ‘add’:

def add(a, b): return a + b
tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
for test, result in tests.items():
   print 'test: adding', test, '==', result, '---', add(*test) == result

There is no other way to call add, other than manually doing something like add(test[0], test[1]), which is ugly. Also, if there are a variable number of variables, the code could get pretty ugly with all the if-statements you would need.

Another place this is useful is for defining Factory objects (objects that create objects for you). Suppose you have some class Factory, that makes Car objects and returns them. You could make it so that myFactory.make_car(‘red’, ‘bmw’, ‘335ix’) creates Car(‘red’, ‘bmw’, ‘335ix’), then returns it.

def make_car(*args):
   return Car(*args)

This is also useful when you want to call a superclass’ constructor.


回答 3

它称为扩展调用语法。从文档中

如果语法* expression出现在函数调用中,则表达式必须计算为序列。来自此序列的元素被视为它们是附加的位置参数。如果存在位置参数x1,…,xN,并且表达式的计算结果为序列y1,…,yM,则等效于使用M + N个位置参数x1,…,xN,y1,…的调用。 ..,yM。

和:

如果语法** expression出现在函数调用中,则expression必须计算为一个映射,该映射的内容被视为其他关键字参数。如果关键字同时出现在表达式中并作为显式关键字参数出现,则会引发TypeError异常。

It is called the extended call syntax. From the documentation:

If the syntax *expression appears in the function call, expression must evaluate to a sequence. Elements from this sequence are treated as if they were additional positional arguments; if there are positional arguments x1,…, xN, and expression evaluates to a sequence y1, …, yM, this is equivalent to a call with M+N positional arguments x1, …, xN, y1, …, yM.

and:

If the syntax **expression appears in the function call, expression must evaluate to a mapping, the contents of which are treated as additional keyword arguments. In the case of a keyword appearing in both expression and as an explicit keyword argument, a TypeError exception is raised.


回答 4

在函数调用中,单星号将列表变成单独的参数(例如zip(*x),与zip(x1,x2,x3)if相同x=[x1,x2,x3]),而双星号将字典变成单独的关键字参数(例如f(**k),与f(x=my_x, y=my_y)if相同)k = {'x':my_x, 'y':my_y}

在函数定义中,反之亦然:单星将任意数量的参数转换为列表,而双引号将任意数量的关键字参数转换为字典。例如,def foo(*x)表示“ foo接受任意数量的参数,可以通过列表x来访问它们(即,如果用户调用foo(1,2,3)x将是[1,2,3])”,并且def bar(**k)表示“ bar可以接受任意数量的关键字参数,并且可以通过字典k进行访问。 (即,如果用户调用bar(x=42, y=23)k将为{'x': 42, 'y': 23})”。

In a function call the single star turns a list into seperate arguments (e.g. zip(*x) is the same as zip(x1,x2,x3) if x=[x1,x2,x3]) and the double star turns a dictionary into seperate keyword arguments (e.g. f(**k) is the same as f(x=my_x, y=my_y) if k = {'x':my_x, 'y':my_y}.

In a function definition it’s the other way around: the single star turns an arbitrary number of arguments into a list, and the double start turns an arbitrary number of keyword arguments into a dictionary. E.g. def foo(*x) means “foo takes an arbitrary number of arguments and they will be accessible through the list x (i.e. if the user calls foo(1,2,3), x will be [1,2,3])” and def bar(**k) means “bar takes an arbitrary number of keyword arguments and they will be accessible through the dictionary k (i.e. if the user calls bar(x=42, y=23), k will be {'x': 42, 'y': 23})”.