Comments 16
1)Если по определению a = [1,2,3] и *a = 1,2,3 (пишу образно для понимания моего не понимания :) ), то в функции printScores(student, *scores) когда вызываем printScores(«Jonathan», 100, 95, 88, 92, 99) получается мы делам обратную операцию *, от всех «следующих аргументов» и тут возникает вопрос, почему не от всех аргументов, а только от «последних», а что если я хочу такую функцию printScores(student, *scores, *otherData)?
И вообще почему нельзя сделать так *a = [1,2,3], что бы получить a = [[1,2,3]]?
2)def printPetNames(owner, **pets) — тут двойная звездочка, в моём понимании по определению это двойная операция *, т.е. если **pets = dog=«Brock», fish=[«Larry», «Curly», «Moe»], turtle=«Shelldon», то *pets = {dog=«Brock», fish=[«Larry», «Curly», «Moe»], turtle=«Shelldon»]} а pets = [{dog=«Brock», fish=[«Larry», «Curly», «Moe»], turtle=«Shelldon»]}]
имхо оператор * имеет только похожее поведение на то что используется в функциях (*args и **kwargs)
1) Если ты напишешь print_scores(arg1, arg2, ..., argN, *scores)
, предполагается, что у тебя N аргументов обязательные, а остальные опциональные, и эти остальные соберутся в отдельный кортеж. То есть конструкция func(arg, *args1, *args2)
невозможна, потому что непонятно, как поделить остальные переменные между args1
и args2
. Если тебе хочется получить два списка аргументов, лучше явно запихни их в списки (fun(arg1=(1, 2, 3), arg2=(4, 5, 6))
)
Писать *a = [1, 2, 3]
нельзя, потому что * это операция распаковки, а не обращение к указателю как в C++. Даже если предположить, что такая конструкция имела бы место, это было бы сильно не pythonic way, потому что гораздо проще и понятнее то, что ты написал: a = [[1, 2, 3]]
.
2) Двойная звёздочка это не двойная распаковка. Это сборка именованных параметров в словарь и наоборот. Одинарная звёздочка на словарь вернёт тебе список ключей. Например,
def fun(*args):
print(', '.join(args))
fun(*{'kek': 4, 'lol': 8, 'cheburek': 15})
напечатает на экране: kek, lol, cheburek
. Логика «двойной оператор это то же самое, что два одинарных» не работает, потому что есть же разница между =
и ==
.
UPD: Коллега ниже отметил, что звезда собирает аргументы в кортеж, исправил оговорку.
Позиционные аргументы приходят в виде кортежа (tuple), который как раз определяется звёздочкой, именованные аргументы приходят в виде словаря dict, и двойная звёздочка тут есть именно задание словаря. То есть при описании функции звёздочки это не операторы, выполняющие какое-либо действие, а именно описание параметров функции, так для printScores(student, *args, **kwargs) мы указываем, что внутри функции мы будем работать с кортежем args и словарём kwargs, по которым будут «разбросаны» все позиционные и именованные аргументы вызова функции. И чтобы не было путаницы, в вызове сначала указываются позиционные параметры (попадают в кортеж args с сохранением последовательности), а потом именованные, то есть вызов printScores('name', param='value', 42) недопустим.
При вызове printScores('name', [1,2,3]) в scores будет кортеж ([1,2,3]), ну или, если кортеж преобразовать в список, то будет список: list(scores) = [[1,2,3]]
Дело в том, что звёздочки — это не процедуры, а часть синтаксиса. Смысл звёздочек в определении процедуры и в выражении, вызывающем процедуру — разный.
*x
в списке формальных аргументов — обозначает, что принимается произвольное число аргументов, которые в теле процедуры будут доступны в кортеже под именем x
. (slurp)
*x
в вызове процедуры — обозначает, что коллекция x
распаковывается подставляется как отдельные аргументы. (splat)
Соответственно, если a = [1, 2, 3]
, то *a
вне контекста вызова процедуры — это синтаксическая ошибка.
Возможно я не понял, что значит "вне контекста вызова процедуры", но позволю себе не согласиться, т.к. следующий код прекрасно работает:
first, *rest = 1, 2, 3, 4
print(rest)
# [2, 3, 4]
Аналогично было бы и со списком:
first, *rest = [1, 2, 3, 4]
Стоило бы хоть PEP8 соблюдать.
*args — array, **kwards — dictionary.
Большое спасибо!
Отличная статья
Всё разложенно по полочкам
Теперь в голове наведён порядок по данному вопросу)
Удачи в дальнейшем написании интересного ;)
Спасибо за полезную статью!
Что такое *args и **kwargs в Python?