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