Python 如何将长度为n的元组解包为m<;n变量

Python 如何将长度为n的元组解包为m<;n变量,python,iterable-unpacking,Python,Iterable Unpacking,在Python 3中,我可以执行以下操作(另请参见扩展Iterable解包): 我该怎么做才能在Python2.x中实现同样的优雅呢 我知道我可以使用单元素访问和切片操作,但我想知道是否有更符合python的方法。到目前为止,我的代码是: a, b = (1, 2, 3)[0], (1, 2, 3)[1:] # a = 1; b = (2, 3) 我可能错了,但据我所知 a, *b = (1, 2, 3) 只是用于对元组进行切片和索引的语法糖。我觉得它很有用,但不是很明确。我认为没有比你发

在Python 3中,我可以执行以下操作(另请参见扩展Iterable解包):

我该怎么做才能在Python2.x中实现同样的优雅呢


我知道我可以使用单元素访问和切片操作,但我想知道是否有更符合python的方法。到目前为止,我的代码是:

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

我可能错了,但据我所知

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

只是用于对元组进行切片和索引的语法糖。我觉得它很有用,但不是很明确。

我认为没有比你发布的方法更好的方法了,但这里有一个替代方法,使用
iter

>>> x = (1,2,3)
>>> i = iter(x)
>>> a,b = next(i), tuple(i)
>>> a
1
>>> b
(2, 3)

不确定上下文,但是.pop(0)呢

我看到在你的例子中有元组,但是如果你想做你所做的事情,我想列表会更合适吗?(除非问题中没有给出它们不可变的充分理由。)


我有一个方便的小功能:

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)

我发现相关文档也给出了一些Python 2.x的示例:

许多算法需要将序列拆分为“第一个,其余”对:

[……]

此外,如果右边的值不是列表,而是iterable,则必须将其转换为列表才能进行切片;为了避免创建此临时列表,必须使用

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

本问题答案中给出的其他方法:

函数参数列表解包方法

需要额外的函数定义/调用:

def unpack(first, *rest): 
  return first, rest
first, rest = unpack( *seq )
我想知道为什么它是在解包函数参数列表中实现的,而不是在正常的元组解包中实现的

发电机方法

。还需要自定义函数实现。在第一个变量的数量上更灵活一些

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)


我想,最具python风格的可能是上面PEP中提到的那些,似乎是显式切片,或者使用多个匿名下划线变量来捕获不需要的值:x,,=tupI实际上对此功能有疑问。它是否符合python“显式优于隐式”的禅宗思想?@jdi它明确指出:将第一项输入到
a
,将所有其他项输入到
b
。我发现这很清楚…这可能是重复的:说实话,我仍然使用py2.7,还没有看到这个3.x的添加。而且它看起来甚至没有一块切片有用。你显然知道你想要第一个元素。与糖相比,你更喜欢切片。虽然它可能只是糖,但如果你左边的列表大于2(嗯,可能大于6或7),它就变得更重要了。切片的问题是,您必须在
=
的两侧进行一些手动计数,这可能会使代码更难维护。我有一个列表,每个列表的长度为4或更多,我希望我可以在python2.7中这样做:
对于myList中未使用的a、b、c、d、*而言:
。有了a、b、c、d的适当名称,我发现它比索引单个变量更具表现力。@mcmlxxvi确实,命名(困难)而且更好。我放弃了我的陈述。这让我想到了一个想法:
def foo(x,*y):返回x,y
,它将是
a,b=foo(*(1,2,3))
。@moooeeep好主意,但你可以简单地做
a,b=foo(1,2,3)
而不是
a,b=foo(*(1,2,3))
@moooeeep:请参阅生产代码中的更新)您将这个方便的小功能保存在哪个文件中?同一个文件?不同的文件?进口什么?你把它和它的朋友打包了吗?所以总体而言,当您访问
只是
,它在真实代码中看起来如何?@naxa:例如
导入myTools。。。。a、 b=myTools.just(…)
到今天为止,PEP3132似乎只适用于Python 3.x。我可以确认,'first,*rest=seq'语法在Python2.7.5中不起作用(您在上面提到了2.x)。@Dave感谢您再次提出这个问题。我决定从引用的部分删除这一部分,因为这是一个混乱的来源,只是与答案无关。
it = iter(seq)
first = it.next()
rest = list(it)
def unpack(first, *rest): 
  return first, rest
first, rest = unpack( *seq )
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)