Почему распаковка дает список вместо кортежа в Python? - PullRequest
5 голосов
/ 25 апреля 2020

Это действительно странно для меня, потому что по умолчанию я думал, что распаковка дает кортежи.

В моем случае я хочу использовать ключи prefix для кэширования, поэтому кортеж предпочтительнее.

# The r.h.s is a tuple, equivalent to (True, True, 100)
*prefix, seed = ml_logger.get_parameters("Args.attn", "Args.memory_gate", "Args.seed")
assert type(prefix) is list

Но я думал, что вместо распаковки будет возвращен кортеж.

Вот соответствующий PEP: https://www.python.org/dev/peps/pep-3132/

- Обновление -

Учитывая комментарии и ответы ниже, в частности, я ожидал, что распаковка даст кортеж, потому что в аргументах функции аргумент распространения всегда является кортежем, а не списком.

Как указывал Джейсон, во время распаковки невозможно было бы заранее узнать длину результата, поэтому с точки зрения реализации универсальное начало должно начинаться как список для динамического добавления c. Преобразование его в список в большинстве случаев является пустой тратой усилий.

Семантически я предпочел бы иметь кортеж для согласованности.

1 Ответ

5 голосов
/ 25 апреля 2020

Эта проблема упоминалась в этом PEP (PEP 3132):

После короткого обсуждения в списке python -3000 [1] ПКП был принят Гвидо в его нынешнем виде. Обсуждались следующие возможные изменения: [...]

  • Попробуйте присвоить помеченной цели тот же тип, что и для итерируемого источника, например, b в a, *b = 'hello' будет присвоен строка 'ello'. Это может показаться хорошим, но невозможно получить правильное согласование со всеми итерациями.

  • Сделайте помеченную цель кортежем вместо списка. Это соответствовало бы *args функции, но усложняло бы дальнейшую обработку результата.

Но, как вы можете видеть, эти функции в настоящее время не реализованы:

In [1]: a, *b, c = 'Hello!'
In [2]: print(a, b, c)
H ['e', 'l', 'l', 'o'] !

Возможно, изменяемые списки больше подходят для этого типа распаковки.

...