В Python 3 я могу сделать следующее (см. также PEP3132 о расширенной распаковке итерабельных файлов):
a, *b = (1, 2, 3)
# a = 1; b = (2, 3)
Что я могу сделать, чтобы добиться такого же элегантного результата в Python 2.x?
Я знаю, что могу использовать одноэлементный доступ и операции нарезки, но мне интересно, есть ли более питонический способ. Мой код на данный момент:
a, b = (1, 2, 3)[0], (1, 2, 3)[1:]
# a = 1; b = (2, 3)
Я узнал, что соответствующие PEP3132 дает некоторые примеры для Python 2.X, а также:
многие алгоритмы требуют расщепления последовательности в "первый, остальные" в паре:
В первый, остальные = сл[0], далее[1:]
[...]
также, если правое значение не список, а итератор, он должен быть преобразован в список, прежде чем он сможет сделать нарезку; чтобы избежать этого временного списка, приходится прибегать к
Это = ИТЭР(сл) первый = он.далее() остальные = список ()
Другие подходы приведенный в ответах на этот вопрос:
Список Аргументов Функции Распаковки Подход
требует дополнительного определения функции/вызов:
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)
Наиболее подходящие для Python, вероятно, будут те, которые упомянуты в выше Пеп, я думаю?
Я могу ошибаться, но насколько я знаю.
a, *b = (1, 2, 3)
это просто синтаксический сахар для нарезки и индексирования кортежей. Я нахожу его полезным, но не очень явным.
Я'ве получил этой маленькой, но удобной функции:
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)
Не уверен в контексте, но как насчет .pop(0)?
Я вижу, что в вашем примере есть кортежи, но если вы хотите делать то, что вы делаете, списки были бы более подходящими, я думаю? (Если только нет какой-то веской причины для того, чтобы они были неизменяемыми, не указанной в вопросе).
b = [1,2,3]
a = b.pop(0)