Для RHS особых проблем нет. ответ здесь говорит об этом хорошо :
У нас это работает, как обычно, в вызовах функций. Он расширяет содержимое итерируемого объекта, к которому он прикреплен. Итак, утверждение:
elements = *iterable
можно рассматривать как:
elements = 1, 2, 3, 4,
это еще один способ инициализации кортежа.
Теперь, что касается LHS. Да, существуют технические причины для использования LHS списка, как указано в обсуждении начальный PEP 3132 для расширения распаковки
Причины можно почерпнуть из разговора на PEP(добавлено в конце).
По сути, это сводится к нескольким ключевым факторам:
- LHS должен был поддерживать «выражение со звездочкой», которое не обязательно ограничивалось только концом.
- RHS должен был позволять принимать различные типы последовательностей, включая итераторы.
- Комбинация двух вышеуказанных пунктов требует манипуляции/мутации содержимого после принятия его в выражение, отмеченное звездочкой.
- Альтернативный подход к обработке, имитирующий итератор, питаемый от RHS, даже если оставить в стороне трудности реализации, был отвергнут Гвидо из-за его непоследовательного поведения.
- Учитывая все вышеперечисленные факторы, кортеж в LHS должен быть сначала списком, а затем преобразован. Тогда этот подход просто добавил бы накладные расходы и не вызывал дальнейшего обсуждения.
Вывод. К решению о разрешении списка в LHS привело сочетание различных факторов, и эти причины были связаны друг с другом.
Соответствующий экстракт для запрета несогласованных типов:
Важный вариант использования предложенной семантики в Python — это когда у вас есть запись переменной длины, первые несколько элементов которой интересны, а остальные менее интересны, но не менее важны. (Если бы вы хотели отбросить все остальное, вы бы просто написали a, b, c = x[:3] вместо a, b, c, *d = x.) В этом случае гораздо удобнее, если тип d фиксируется операцией, так что вы можете рассчитывать на его поведение.
В конструкции функции filter() в Python 2 есть ошибка (которая будет исправлена в версии 3.0 путем превращения ее в итератор, кстати): если на входе кортеж, то на выходе тоже кортеж, но если на входе список или что-то еще, результатом будет список. Это совершенно безумная подпись, так как это означает, что вы не можете рассчитывать на то, что результатом будет список, и что это будет кортеж -- если вам нужно, чтобы это был тот или другой , вы должны преобразовать его в единицу, что является пустой тратой времени и места. Пожалуйста, давайте не будем повторять эту ошибку в дизайне. – Гвидо.
Я также попытался воссоздать частично процитированный разговор, относящийся к приведенному выше резюме. ">Источник Выделено мной.
1.
В списках аргументов *args исчерпывает итераторы, преобразовывая их в кортежи. Я думаю, было бы запутанно, если бы *args в распаковке кортежа не делало то же самое.
В связи с этим возникает вопрос, почему исправление создает списки, а не кортежи. В чем причина этого?
Стив
2.
ИМО, вполне вероятно, что вы захотите дополнительно обработать полученную последовательность, в том числе изменить ее.
Георг
3.
Ну, если это то, к чему вы стремитесь, то я ожидаю, что будет полезнее, чтобы распаковка генерировала не списки, а тот же тип, с которого вы начали, например. если я начал со строки, я, вероятно, захочу продолжить использовать строки:: --дополнительный текст обрезан
4.
При работе с итератором длина заранее неизвестна, поэтому единственный способ получить кортеж — сначала создать список, а затем создать из него кортеж. /strong> Грег
5.
Ага. Это была одна из причин, по которой было предложено, чтобы *args появлялись только в конце распаковки кортежа.
Стив
пара совещаний пропущена
6.
Я не думаю, что возвращение заданного типа является целью, к которой следует стремиться, поскольку это может работать только для фиксированного набора известных типов. Учитывая произвольный тип последовательности, невозможно зная, как создать новый экземпляр с указанным содержимым.
-- Грег
пропущенные встречи
7.
Я предполагаю, что:
- списки возвращают списки
- кортежи возвращают кортежи
- Контейнеры XYZ возвращают контейнеры XYZ
- итерации, не являющиеся контейнерами, возвращают итераторы.
Как вы предлагаете различать два последних случая? Попытка нарезать его и перехватить исключение недопустима, IMO, так как это может слишком легко маскировать ошибки.
-- Грег
8.
Но я ожидаю менее полезного. Он также не поддерживает "a, *b, c = ". Из точки зрения реализации, если у вас есть неизвестный объект в RHS, у вас есть попробовать нарезать его, прежде чем пытаться повторить его; это может вызвать проблемы например. если объект является defaultdict -- поскольку x[3:] реализован как x[slice(None, 3, None)], defaultdict даст вам значение по умолчанию. Я бы скорее определил это с точки зрения итерации объекта до тех пор, пока он не будет исчерпан, что можно оптимизировать для определенных известных типов, таких как списки и кортежи.
-- --Гвидо ван Россум
person
Paritosh Singh
schedule
21.05.2019