избыточные позиционные параметры, распаковывая списки аргументов или кортежи и расширенную повторяемую распаковку

Этот вопрос будет довольно долгим, таким образом, я приношу извинения заблаговременно.

В Python мы можем использовать * в следующих трех случаях:

I. При определении функции, что мы хотим быть вызываемыми с произвольным числом аргументов, такой как в этом примере:

def write_multiple_items(file, separator, *args):
    file.write(separator.join(args))

В этом случае избыточные позиционные параметры собраны в кортеж.

II. Обратный случай - когда аргументы уже находятся или в списке или в кортеже, и мы хотим распаковать их для вызова функции, требующего отдельных позиционных параметров, такой как в этом примере:

>>> range(3, 6)             # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args)            # call with arguments unpacked from a list
[3, 4, 5]

III. Запуск с Python 3, * также используется в контексте расширенного списка или распаковки кортежа, такой как в этом примере для кортежей:

>>> a, *b, c = range(5)
>>> b
[1, 2, 3]

или для списков:

>>> [a, *b, c] = range(5)
>>> b
[1, 2, 3]

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

Таким образом, вот вопрос: в случае, если я, дополнительные args собраны в кортеж, в то время как в случае, если III дополнительные объекты присвоены списку. Откуда это несоответствие? Единственное объяснение, которое я мог найти, было в PEP 3132, который говорит что:

Возможные обсужденные изменения были:

[...]

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

Однако с педагогической точки зрения это отсутствие непротиворечивости проблематично, особенно учитывая то, что, если Вы хотели обработать результат, Вы могли бы всегда говорить, что список (b) (принимающий b в вышеупомянутых примерах был кортеж). Я пропускаю что-то?

5
задан Glenn Maynard 8 July 2010 в 03:10
поделиться

2 ответа

В Python мы можем использовать * в

Вы имеете в виду prefix *, конечно -- infix * используется для умножения.

Однако, с педагогической точки зрения с педагогической точки зрения это отсутствие последовательности является проблематичным, особенно учитывая, что если бы вы хотели обработать результат, вы всегда можете сказать list(b) (предполагая, что b в приведенных выше примерах был кортежем). Я что-то упускаю?

Я бы сказал, что проблема дизайна (старая и очень давняя! ) заключается в том, что при получении произвольных аргументов вы получаете их в виде кортежа, тогда как список был бы более полезен во многих случаях без каких-либо реальных недостатков (крошечный объем дополнительной обработки и памяти, который может потребоваться для создания списка вместо кортежа, ничтожен в контексте накладных расходов на вызов функции - или распаковку последовательности, если уж на то пошло; дополнительная обработка и память, необходимые для создания списка и кортежа, действительно более раздражающие).

С кортежем можно делать очень мало, но не со списком - в основном, только хэшировать его (чтобы использовать в качестве элемента набора или ключа dict) - в то время как список предлагает гораздо больше дополнительных функций, и не только для целей его изменения... такие методы, как count и index также полезны.

7
ответ дан 18 December 2019 в 11:52
поделиться

Вы пропустили один.

IV. Кроме того, в Python 3 голый * в списке аргументов отмечает конец позиционных аргументов, что позволяет использовать аргументы, содержащие только ключевое слово .

def foo(a, b, *, key = None):
    pass

Это можно назвать foo (1, 2, key = 3) , но не foo (1, 2, 3) .

8
ответ дан 18 December 2019 в 11:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: