Помните, что списки не реализованы как односвязные списки в Python, поэтому эта операция является дорогостоящей (например, необходимо скопировать весь список). В зависимости от того, чего вы хотите достичь, это может быть или не быть проблемой. Я просто упомянул об этом, потому что этот тип деструктурирования списка часто встречается в функциональных языках, где на самом деле это очень дешевая операция.
Новой функцией в 3.x является использование *оператора при распаковке для обозначения любых дополнительных значений. Это описано в PEP 3132 - Extended Iterable Unpacking . Это также дает преимущество работы с любыми итерациями, а не только с последовательностями.
Это также действительно читается.
Как описано в PEP, если вы хотите сделать эквивалент в версии 2.x (без создания временного списка), вы должны сделать это:
it = iter(iterable)
head, tail = next(it), list(it)
Как отмечено в комментариях, это также дает возможность получить значение по умолчанию, headа не генерировать исключение. Если вы хотите такое поведение, next()принимает необязательный второй аргумент со значением по умолчанию, поэтому next(it, None)он даст вам, Noneесли бы не было элемента head.
Естественно, если вы работаете со списком, самый простой способ без синтаксиса 3.x:
извините, я неправильно использовал термин "хвост". Я имею в виду то, что я говорю в примере, это список без первого элемента
Джакомо д'Антонио
1
@NikolayFominyh Они оба одинаковы - они оба берут элемент головы и создают новый список, содержащий элементы хвоста. Никакой разницы в сложности. Другой класс мог бы лениво реализовать __getitem__/ __setitem__выполнять хвостовую операцию, но встроенный список этого не делает.
Gareth Latty 04
2
В списке из 800 элементов, делающих это 1M раз, у меня 2,8 секунды для головы, решение * tail = seq и только 1,8 секунды для решения head, tail = seq [0], seq [1:]. Для списков нарезка еще быстрее.
Cabu
2
@CMCDragonkai Нет, основной класс списка Python - это список массивов. Это будет O (n), поскольку это включает копирование хвоста в новый список (с одним получением O (1) для головы).
Гарет Латти,
1
Этот красивый синтаксис - еще одна причина перейти наpython 3.x
Похоже, что deque (list_instance) имеет сложность O (N). Я ошибся?
Никита Конин 08
1
@ НикитаКонин, вы правы насчет постройки двора. Однако, если вы хотите получить доступ к первому элементу более одного раза, то head, tail = l.popleft(), lэто ~ O (1). head, tail = seq[0], seq[1:]равно O (n).
Николай Фоминых
Похоже, вы можете просто сделать, head = l.popleft()и tailэто просто псевдоним для l. Если lизменения tailизменения тоже.
почему бы вы сделали это вместо того, чтобы просто head, tail = lst[0], lst[1:]? если OP подразумевает использование буквального слова, то он может вручную разделить голову и хвостhead, tail = 1, [1, 2, 3, 5, 8, 13, 21, 34, 55]
Филипе Пина
1
(1) Вопрос Op заключался в том, можно ли сделать это в одной строке (поэтому нет lst = ...в предыдущей строке). (2) Выполнение head, tail = lst[0], lst[1:]оставляет код открытым для побочных эффектов (рассмотрите head, tail = get_list()[0], get_list()[1:]) и отличается от формы Op head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55].
BobIsNotMyName
При этом я признаю, что это плохой запутанный способ получить голову / хвост. Но я подумал, что это лучший ответ для Python 2 на конкретный вопрос Op.
BobIsNotMyName
1
Основываясь на решении Python 2 от @GarethLatty , ниже представлен способ получить однострочный эквивалент без промежуточных переменных в Python 2.
t=iter([1, 1, 2, 3, 5, 8, 13, 21, 34, 55]);h,t = [(h,list(t)) for h in t][0]
Если вам нужно, чтобы он был защищен от исключений (т.е. поддерживал пустой список), добавьте:
t=iter([]);h,t = ([(h,list(t)) for h in t]+[(None,[])])[0]
Если вы хотите сделать это без точки с запятой, используйте:
h,t = ([(h,list(t)) for t in [iter([1,2,3,4])] for h in t]+[(None,[])])[0]
Ответы:
В Python 3.x вы можете сделать это красиво:
>>> head, *tail = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] >>> head 1 >>> tail [1, 2, 3, 5, 8, 13, 21, 34, 55]
Новой функцией в 3.x является использование
*
оператора при распаковке для обозначения любых дополнительных значений. Это описано в PEP 3132 - Extended Iterable Unpacking . Это также дает преимущество работы с любыми итерациями, а не только с последовательностями.Это также действительно читается.
Как описано в PEP, если вы хотите сделать эквивалент в версии 2.x (без создания временного списка), вы должны сделать это:
Как отмечено в комментариях, это также дает возможность получить значение по умолчанию,
head
а не генерировать исключение. Если вы хотите такое поведение,next()
принимает необязательный второй аргумент со значением по умолчанию, поэтомуnext(it, None)
он даст вам,None
если бы не было элемента head.Естественно, если вы работаете со списком, самый простой способ без синтаксиса 3.x:
head, tail = seq[0], seq[1:]
источник
__getitem__
/__setitem__
выполнять хвостовую операцию, но встроенный список этого не делает.python 3.x
>>> mylist = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] >>> head, tail = mylist[0], mylist[1:] >>> head 1 >>> tail [1, 2, 3, 5, 8, 13, 21, 34, 55]
источник
Однако для сложности
head,tail
операции O (1) вы должны использоватьdeque
.Следующим способом:
from collections import deque l = deque([1,2,3,4,5,6,7,8,9]) head, tail = l.popleft(), l
Это полезно, когда вы должны перебирать все элементы списка. Например, при наивном слиянии двух разделов в сортировке слияния.
источник
head, tail = l.popleft(), l
это ~ O (1).head, tail = seq[0], seq[1:]
равно O (n).head = l.popleft()
иtail
это просто псевдоним дляl
. Еслиl
измененияtail
изменения тоже.Python 2 с использованием лямбда
>>> 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:]
? если OP подразумевает использование буквального слова, то он может вручную разделить голову и хвостhead, tail = 1, [1, 2, 3, 5, 8, 13, 21, 34, 55]
lst = ...
в предыдущей строке). (2) Выполнениеhead, tail = lst[0], lst[1:]
оставляет код открытым для побочных эффектов (рассмотритеhead, tail = get_list()[0], get_list()[1:]
) и отличается от формы Ophead, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
.Основываясь на решении Python 2 от @GarethLatty , ниже представлен способ получить однострочный эквивалент без промежуточных переменных в Python 2.
t=iter([1, 1, 2, 3, 5, 8, 13, 21, 34, 55]);h,t = [(h,list(t)) for h in t][0]
Если вам нужно, чтобы он был защищен от исключений (т.е. поддерживал пустой список), добавьте:
t=iter([]);h,t = ([(h,list(t)) for h in t]+[(None,[])])[0]
Если вы хотите сделать это без точки с запятой, используйте:
h,t = ([(h,list(t)) for t in [iter([1,2,3,4])] for h in t]+[(None,[])])[0]
источник