Этот вопрос будет довольно долгим, таким образом, я приношу извинения заблаговременно.
В 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 в вышеупомянутых примерах был кортеж). Я пропускаю что-то?
В Python мы можем использовать
*
в
Вы имеете в виду prefix *
, конечно -- infix *
используется для умножения.
Однако, с педагогической точки зрения с педагогической точки зрения это отсутствие последовательности является проблематичным, особенно учитывая, что если бы вы хотели обработать результат, вы всегда можете сказать list(b) (предполагая, что b в приведенных выше примерах был кортежем). Я что-то упускаю?
Я бы сказал, что проблема дизайна (старая и очень давняя! ) заключается в том, что при получении произвольных аргументов вы получаете их в виде кортежа, тогда как список был бы более полезен во многих случаях без каких-либо реальных недостатков (крошечный объем дополнительной обработки и памяти, который может потребоваться для создания списка вместо кортежа, ничтожен в контексте накладных расходов на вызов функции - или распаковку последовательности, если уж на то пошло; дополнительная обработка и память, необходимые для создания списка и кортежа, действительно более раздражающие).
С кортежем можно делать очень мало, но не со списком - в основном, только хэшировать его (чтобы использовать в качестве элемента набора или ключа dict) - в то время как список предлагает гораздо больше дополнительных функций, и не только для целей его изменения... такие методы, как count
и index
также полезны.
Вы пропустили один.
IV. Кроме того, в Python 3 голый *
в списке аргументов отмечает конец позиционных аргументов, что позволяет использовать аргументы, содержащие только ключевое слово .
def foo(a, b, *, key = None):
pass
Это можно назвать foo (1, 2, key = 3)
, но не foo (1, 2, 3)
.