При вызове функции одно имя параметра передано одновременно позиционно и по ключу: какое правило связывания аргументов определяет результат?
Если один параметр получает значение одновременно из позиционной и именованной части вызова, Python немедленно выбрасывает TypeError о повторной передаче аргумента. Тело функции не начинает выполняться, потому что ошибка возникает на этапе связывания фактических аргументов с параметрами.
Модель вызова функций в Python поддерживает два способа передачи аргументов: по позиции и по имени. Это позволяет использовать короткие вызовы для очевидных параметров и явно указывать параметры, когда важны читаемость или порядок.
Такая гибкость требует однозначного правила связывания. Python не выбирает одно из двух значений молча, поскольку это могло бы скрыть ошибку вызывающего кода.
Ошибка возникает, когда параметр, допускающий оба способа передачи, уже получил позиционное значение, а затем получает второе значение по имени. Аналогичный конфликт возможен при распаковке позиционной последовательности или именованного отображения.
Если разработчик ожидает, что именованное значение «перезапишет» позиционное, он неверно понимает семантику вызова. В результате функция не выполнится, побочные эффекты внутри её тела не произойдут, а исключение нужно будет обработать или устранить на месте вызова.
Сначала Python сопоставляет позиционные аргументы с доступными позиционными параметрами слева направо. Затем именованные аргументы сопоставляются по именам. Если именованный аргумент указывает на параметр, которому уже присвоено значение позиционно, обнаруживается дубликат и возникает TypeError.
В этом примере timeout сначала получает значение 5, а затем для него предлагается значение 10. Строка внутри функции не выводится: связывание аргументов завершается ошибкой раньше.
Значение по умолчанию не разрешает конфликт. Оно используется только тогда, когда параметр вообще не получил аргумент. Распаковка **mapping подчиняется тому же правилу: если ключ уже был передан явно или ранее появился через другую распаковку, возникает ошибка дублирования.
Важно различать виды параметров. Позиционно-именованный параметр допускает оба способа передачи и потому может получить такой конфликт. Только позиционный параметр нельзя передать по имени, а только именованный нельзя передать позиционно; для них действуют отдельные ошибки о недопустимом способе передачи.
В клиенте HTTP-функция принимает адрес и тайм-аут. Один слой передаёт тайм-аут позиционно, а другой добавляет общие параметры через словарь именованных аргументов. При совпадении ключа запрос не отправляется, хотя разработчик мог ожидать переопределения значения.
Можно удалить значение из словаря перед распаковкой. Это сохраняет единую точку выбора параметра, но требует явно контролировать приоритеты и усложняет подготовку аргументов.
Другой вариант — передавать такой параметр только именованно. Это делает вызовы самодокументируемыми и предотвращает позиционно-именованные конфликты, но требует изменить интерфейс функции или дисциплину её использования.
На практике предпочтителен второй вариант для настроек вроде тайм-аутов: параметр объявляют только именованным и передают его единообразно. Ошибка обнаруживается сразу на границе вызова, а не превращается в неявный конфликт конфигураций.
1. Выполнится ли тело функции до обнаружения дубликата аргумента?
Нет. Сначала Python формирует локальное связывание параметров и проверяет корректность вызова. Только после успешного связывания начинается выполнение тела, поэтому его побочные эффекты не происходят.
2. Может ли значение по умолчанию разрешить повторную передачу параметра?
Нет. Значение по умолчанию применяется лишь при отсутствии фактического аргумента. Если параметр уже получил значение позиционно или по имени, наличие значения по умолчанию ничего не меняет и не превращает повторную передачу в допустимое переопределение.
3. Что произойдёт при повторяющемся ключе после распаковки именованных аргументов?
Python также выбросит TypeError, если один и тот же параметр получает значения из нескольких источников. Механизм не предполагает автоматического приоритета последнего значения: явная ошибка безопаснее молчаливого изменения конфигурации.