Позиционные-only и keyword-only параметры в Python
@python_quizРазберем этот квиз
Короткий пример для анализа:

Что здесь происходит и почему код работает именно так — разберём синтаксис и варианты вызова.
Синтаксис: / и *
- Символ
/в списке параметров означает, что все параметры слева от него — positional-only (только позиционные). Их нельзя передать по имени. - Символ
*в списке параметров означает, что все параметры справа от него — keyword-only (только по ключу). Их нельзя передать позиционно. - Параметры между
/и*— обычные, их можно передавать и позиционно, и по имени.
В нашей функции:
- a — positional-only (из-за
/). - b — обычный параметр (можно позиционно или по ключу).
- c — keyword-only (из-за
*).
Почему print(merge(1, b=2, c=3)) выводит 6
Вызов разбирается так:
- a получает 1 (передан позиционно) — допустимо.
- b получает 2 (передан по имени) — допустимо, потому что b не positional-only.
- c получает 3 (передан по имени) — обязательно должен быть по имени, это keyword-only.
Сумма 1 + 2 + 3 = 6, поэтому на экран выводится 6.

Разбор возможных вариантов вызова и ошибок
Примеры корректных и некорректных вызовов с объяснениями:
1) Вызов, аналогичный исходному:

2) Попытка передать a по имени — вызовет TypeError, потому что a — positional-only:

3) Передать все позиционно — ошибка, потому что c — keyword-only:

4) Передать b позиционно, c по имени — корректно:

5) Попытка передать c позиционно и b по имени (перестановка) — приведёт к той же ошибке, что и пункт 3:

(Последний пример показывает, что порядок именованных аргументов не важен, если они допустимы. Но c всё равно должен быть передан по имени.)
Практические советы
- Используйте positional-only параметры, чтобы зафиксировать интерфейс и не позволять вызывать функцию с неявными именами для первых аргументов (удобно для производительности и совместимости API).
- Используйте keyword-only параметры, чтобы сделать вызовы самодокументируемыми и предотвратить ошибки при неверном порядке аргументов.
- Читая сигнатуру функции с
/и*, всегда определите, какие аргументы можно передавать по позиции, а какие — только по имени.
Вывод
Синтаксис с / и * даёт тонкий контроль над тем, как параметры могут передаваться. В примере a — только позиционный, b — гибкий, c — только по ключу; такой набор делает вызов merge(1, b=2, c=3) корректным и приводит к выводу 6.