web-dev-qa-db-ja.com

辞書をタプルとして解凍できるのはなぜですか?

今日、私は例外をスローしなかった1つのステートメントを見ました。誰かがその背後にある理論を説明できますか?

>>> x, y = {'a': 2, 'b': 5}
>>> x
'a'
>>> y
'b'
61
nik_kgp

Pythonでは、すべての iterable を解凍できます1

>>> x,y,z = [1, 2, 3]  # A list
>>> x,y,z
(1, 2, 3)
>>> x,y,z = 1, 2, 3  # A Tuple
>>> x,y,z
(1, 2, 3)
>>> x,y,z = {1:'a', 2:'b', 3:'c'}  # A dictionary
>>> x,y,z
(1, 2, 3)
>>> x,y,z = (a for a in (1, 2, 3))  # A generator
>>> x,y,z
(1, 2, 3)
>>>

さらに、辞書を反復処理すると、そのキーのみが返されるため、次のようになります。

>>> for i in {1:'a', 2:'b', 3:'c'}:
...     print i
...
1
2
3
>>>

ディクショナリ(それを反復処理する)をアンパックすると、同様にそのキーのみがアンパックされます。


1実際、すべてのイテラブルをアンパックできると言わなければなりませんアンパックする名前がイテラブルの長さに等しい限り

>>> a,b,c = [1, 2, 3]  # Number of names == len(iterable)
>>>
>>> a,b = [1, 2, 3]  # Too few names
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
>>>
>>> a,b,c,d = [1, 2, 3]  # Too many names
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: need more than 3 values to unpack
>>>

しかし、これはPython 2.xの場合のみです。Python 3.xでは、 拡張された反復可能なアンパック )があります。任意の(有限の)サイズのイテラブルを必要な名前だけに解凍できます。

>>> # Python 3.x interpreter
...
>>> a, *b, c = [1, 2, 3, 4]
>>> a, b, c
(1, [2, 3], 4)
>>>
>>> a, *b = [1, 2, 3, 4]
>>> a, b
(1, [2, 3, 4])
>>>
>>> *a, b, c = [1, 2, 3, 4]
>>> a, b, c
([1, 2], 3, 4)
>>>
63
iCodez

dictを繰り返すと、キーが繰り返されます。 dictリテラルには正確に2つのキーがあるため、2タプルに解凍できます。

(python 3.7より前、または他のいくつかの実装ではおそらくそれ以前)dictは順序付けられておらず、x == 'b'およびy == 'a'はそのコードの完全に合法的な結果になります。

20
Wooble

辞書を反復処理すると、そのキーが取得されます

data = {'a': 2, 'b': 5}
for key in data:
    print key

解凍は、オブジェクトを繰り返し処理し、指定された変数に要素を配置することに他なりません。

keys = Tuple(data) # gives ('a', 'b')
x, y = ('a', 'b')
8
Daniel

その背後にあるロケット科学はありません。 dictは反復可能であり、各反復でキーを返します。 Tuple()は(有限である限り)引数として反復可能なものを受け取ることができるので、次のようになります。

>>>Tuple({'a': 2, 'b': 5})
('a','b')

これを見ると、開梱が図のように機能することが簡単に推測できます。さらに、任意のfinite iterableを解凍できます。

>>> i = iter(range(3))
>>> a,b,c = i
>>> a,b,c
(0, 1, 2)
7
Paulo Bu

反復可能なコンテキストでは、dictは(順序付けられていない)キーのコレクションとして扱われます。これは、list(some_dict)を実行したときに取得されるものであり、dictでkeys()を呼び出すのと同じです。

_>>> d = {'a': 3, 'b': 5}
>>> list(d)
['a', 'b']
>>> d.keys()
['a', 'b']
_

ただし、それ以上のこともできます。

最初にペアのリストに変換すると、両方のdictの両方のキーおよび値を解凍できます。

_>>> d = {'a': 3, 'b': 5}
>>> d_pairs = d.items()
>>> print d_pairs
[('a', 3), ('b', 5)]
>>> ((k1, v1), (k2, v2)) = d_pairs
>>> print k1, v1, k2, v2
a 3 b 5
_

またはペアが必要な場合

_>>> p1, p2 = d_pairs
>>> print p1, p2
('a', 3) ('b', 5)
_

または、たとえば、キーだけです。

_>>> ((k1, _), (k2, _)) = d_pairs
>>> print k1, k2
a b
_

等.

しかしもちろん、辞書(つまり、一般的にはPython)だけでなく、順序付けられていない方法でアイテムが含まれているため、items()(Pythonの場合)も返されますそれらは一見任意の順序であるため、どのキーがどの変数に格納されるかを知る方法はありません。

_>>> ((k1, v1), (k2, v2)) = {'bar': 3, 'foo': 5}.items()
>>> print k1, v1, k2, v2
foo 5 bar 3
_

ご覧のとおり、items()によって返されるペアの順序は、定義の順序と比較して逆になっています。

5
Erik Allik