web-dev-qa-db-ja.com

長さnからm <nの変数のタプルをアンパックする方法

Python 3では次のことができます(拡張イテラブルアンパックの PEP3132 も参照):

a, *b = (1, 2, 3)
# a = 1; b = (2, 3)

Python 2.xで同じようにエレガントにするにはどうすればよいですか?


私は単一要素のアクセスとスライス操作を使用できることを知っていますが、もっとPythonicの方法があるのだろうかと思います。これまでの私のコード:

a, b = (1, 2, 3)[0], (1, 2, 3)[1:]
# a = 1; b = (2, 3)
44
moooeeeep

関連する PEP3132 がPython 2.xの例も示していることがわかりました。

多くのアルゴリズムでは、シーケンスを「最初、残り」のペアに分割する必要があります。

first, rest = seq[0], seq[1:]

[...]

また、右側の値がリストではなく反復可能な場合、スライスを実行する前にリストに変換する必要があります。この一時リストを作成しないようにするには、

it = iter(seq)
first = it.next()
rest = list(it)

この質問への回答で与えられた他のアプローチ:

関数の引数リストのアンパックアプローチ

追加の関数定義/呼び出しが必要です:

def unpack(first, *rest): 
  return first, rest
first, rest = unpack( *seq )

関数の引数リストをアンパックするのになぜ実装されているのかと思いますが、通常のタプルのアンパックには実装されていません.

発電機アプローチ

クレジット 。カスタム関数の実装も必要です。 first変数の数に関してもう少し柔軟です。

def unpack_nfirst(seq, nfirst):
  it = iter(seq)
  for x in xrange(nfirst):
    yield next(it, None)
  yield Tuple(it)
first, rest = unpack_nfirst(seq, 1)

恐らく最もPythonicは上記のPEPで言及されているものでしょう。

30
moooeeeep

この便利な小さな機能があります:

def just(n, seq):
    it = iter(seq)
    for _ in range(n - 1):
        yield next(it, None)
    yield Tuple(it)

例えば:

a, b, c = just(3, range(5))
print a, b, c
## 0 1 (2, 3, 4)

以下の引数でも動作します:

a, b, c = just(3, ['X', 'Y'])
print a, b, c
## X Y ()

コメントへの応答として、以下を定義することもできます。

def take2(a, *rest): return a, rest
def take3(a, b, *rest): return a, b, rest
def take4(a, b, c, *rest): return a, b, rest
... etc

次のように使用します:

p = (1,2,3)
a, b = take2(*p)
print a, b
## 1 (2, 3)
8
georg

私は間違っているかもしれませんが、私が知る限り

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

タプルのスライスとインデックス付けのための構文糖衣です。便利ではあるが、あまり明確ではない。

8

あなたが投稿したものより良い方法はないと思いますが、ここではiterを使用する代替方法があります

>>> x = (1,2,3)
>>> i = iter(x)
>>> a,b = next(i), Tuple(i)
>>> a
1
>>> b
(2, 3)
4
jamylak

コンテキストについてはわかりませんが、.pop(0)についてはどうでしょうか?

あなたの例にはタプルがありますが、あなたがやることをしたい場合は、リストがより適していると思いますか? (質問に記載されていない不変であるという正当な理由がない限り)

b = [1,2,3]
a = b.pop(0)
2
Bittrance