Практическая ситуация: в публичной функции часть параметров нужно запретить передавать позиционно. Каким механизмом Python это обеспечивает?
Для этого используют параметры, доступные только по имени: в сигнатуре функции ставят отдельный символ * перед такими параметрами. Попытка передать их позиционно завершится исключением TypeError.
Механизм появился в Python 3 как средство сделать вызовы функций более явными и устойчивыми к изменениям API. Он решает проблему неоднозначных позиционных аргументов, когда вызывающему коду трудно понять назначение параметра, а добавление нового параметра может изменить смысл существующих вызовов.
Позиционные аргументы удобны для небольшого числа очевидных параметров, но плохо подходят для настроек, флагов и редко используемых опций. Вызов с несколькими значениями одного типа может быть формально корректным, но практически непонятным и легко привести к ошибке.
Если библиотека позднее меняет порядок таких параметров, старый позиционный вызов может начать означать другое. Обязательная передача по имени делает намерение вызывающего кода явным и снижает риск несовместимых изменений.
Символ * в сигнатуре отделяет позиционные параметры от keyword-only-параметров. Всё, что находится справа от него, можно передать только с указанием имени.
В примере host допускает позиционную передачу, а timeout и secure требуют ключевого синтаксиса. Если у keyword-only-параметра нет значения по умолчанию, он остаётся обязательным, но всё равно должен передаваться по имени.
Такой механизм проверяется Python во время связывания аргументов с параметрами, до выполнения тела функции. Это отличается от ручной проверки внутри функции: при ручной проверке некорректный вызов уже мог пройти через дополнительную логику, а сообщение об ошибке обычно будет менее точным.
Следует различать * как разделитель параметров и *args как параметр, собирающий произвольное количество позиционных аргументов. После *args все последующие именованные параметры также становятся keyword-only. Ограничение повышает ясность API, но делает вызовы более многословными и может потребовать обновления существующего кода.
В библиотеке HTTP-клиент имеет параметры адреса, тайм-аута, повторных попыток и проверки сертификата. Вариант с одной длинной последовательностью позиционных параметров краток, но вызов вроде request(url, 10, 3, False) трудно безопасно прочитать.
Можно оставить все параметры позиционными, но это ухудшает читаемость и делает перестановку параметров опасной. Можно принимать произвольные **kwargs, однако тогда ошибки в именах параметров обнаруживаются только собственной валидацией, а часть информации о контракте теряется.
Выбранный вариант — оставить обязательный адрес позиционным, а настройки сделать keyword-only: request(url, timeout=10, retries=3, verify=False). Такой API явно показывает назначение аргументов, автоматически отклоняет неизвестный способ передачи и упрощает расширение сигнатуры. Цена решения — необходимость указывать имена для параметров настройки.
Нет. Положение после * определяет только способ передачи, а не наличие значения по умолчанию. Параметр без значения по умолчанию обязателен, поэтому его нужно указать по имени; отсутствие такого аргумента вызовет TypeError.
*args?Да. После параметра *args все следующие параметры автоматически становятся доступными только по имени. Это позволяет функции принять произвольное число позиционных аргументов и одновременно задать именованные настройки с проверяемой сигнатурой.
**kwargs?Он будет собран в словарь kwargs, а не отклонён автоматически. Это удобно для проксирования или расширяемых API, но ослабляет проверку контракта: опечатка в имени может незаметно попасть в словарь. Если строгая сигнатура важнее расширяемости, **kwargs добавлять не следует или его содержимое нужно явно валидировать.