Existe uma maneira pythônica de desempacotar uma lista no primeiro elemento e a "cauda" em um único comando?
Por exemplo:
>> head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
Existe uma maneira pythônica de desempacotar uma lista no primeiro elemento e a "cauda" em um único comando?
Por exemplo:
>> head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
Respostas:
No Python 3.x, você pode fazer isso muito bem:
>>> head, *tail = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
Um novo recurso no 3.x é usar o *operador na descompactação, para significar quaisquer valores extras. É descrito em PEP 3132 - Desempacotamento Iterável Estendido . Isso também tem a vantagem de trabalhar em qualquer iterável, não apenas em sequências.
Também é muito legível.
Conforme descrito no PEP, se você quiser fazer o equivalente em 2.x (sem potencialmente fazer uma lista temporária), você deve fazer o seguinte:
it = iter(iterable)
head, tail = next(it), list(it)
Conforme observado nos comentários, isso também fornece uma oportunidade de obter um valor padrão para, em headvez de lançar uma exceção. Se você deseja este comportamento, next()recebe um segundo argumento opcional com um valor padrão, então next(it, None)forneceria Nonese não houvesse elemento head.
Naturalmente, se você estiver trabalhando em uma lista, a maneira mais fácil sem a sintaxe 3.x é:
head, tail = seq[0], seq[1:]
__getitem__/ __setitem__para fazer a operação final preguiçosamente, mas a lista interna não o faz.
python 3.x
No entanto, para complexidade de head,tailoperação O (1) , você deve usar deque.
Caminho seguinte:
from collections import deque
l = deque([1,2,3,4,5,6,7,8,9])
head, tail = l.popleft(), l
É útil quando você deve iterar por todos os elementos da lista. Por exemplo, na mesclagem ingênua de 2 partições na classificação de mesclagem.
head, tail = l.popleft(), lé ~ O (1). head, tail = seq[0], seq[1:]é O (n).
head = l.popleft()e tailé apenas um apelido para l. Se las tailmudanças também mudarem.
Python 2, usando lambda
>>> head, tail = (lambda lst: (lst[0], lst[1:]))([1, 1, 2, 3, 5, 8, 13, 21, 34, 55])
>>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
head, tail = lst[0], lst[1:]? se OP significa usar um literal então ele poderia dividir cabeça e cauda manualmentehead, tail = 1, [1, 2, 3, 5, 8, 13, 21, 34, 55]
lst = ...na linha anterior). (2) Fazer head, tail = lst[0], lst[1:]deixa o código aberto a efeitos colaterais (considere head, tail = get_list()[0], get_list()[1:]) e é diferente da forma de Op head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55].
Com base na solução Python 2 de @GarethLatty , o seguinte é uma maneira de obter um equivalente de linha única sem variáveis intermediárias em Python 2.
t=iter([1, 1, 2, 3, 5, 8, 13, 21, 34, 55]);h,t = [(h,list(t)) for h in t][0]
Se você precisa que seja à prova de exceção (ou seja, suporte para lista vazia), adicione:
t=iter([]);h,t = ([(h,list(t)) for h in t]+[(None,[])])[0]
Se você quiser fazer isso sem o ponto-e-vírgula, use:
h,t = ([(h,list(t)) for t in [iter([1,2,3,4])] for h in t]+[(None,[])])[0]