Функция принимает n
аргументы. Вы предоставили m
. n != m
. Вероятно, это ошибка в чьем-то коде или признак непонимания чьего-то API. Кроме того, я не думаю, что мы могли бы договориться о значимой, полезной семантике, что должно произойти в этом случае. Следует ли игнорировать лишние аргументы? Это позволило бы таким ошибкам пройти, и, поскольку «ошибки никогда не пройдут молча», это неприемлемо. Аналогичным образом, предоставление некоторого значения по умолчанию для пропущенных аргументов допускает тихое неправильное поведение в случае опечаток и т. Д. И, таким образом, нарушает тот же принцип, не говоря уже о том, что «явный лучше, чем неявный», т. Е. Если вы хотите передать какое-то специальное значение, вы должны просто запиши это.
PEP, на который вы ссылаетесь, и его if args: raise TypeError(...)
семантика применяются только к функциям с аргументами только для ключевых слов, которые не принимают varargs и используют простой *
в списке параметров для кодификации этого. Есть функции, которые принимают ограниченное количество позиционных аргументов и выиграют от аргументов только для ключевых слов, но varargs не будет для них значимым. Для них существует простой *
, позволяющий разрешать аргументы только для ключевых слов, не требуя шаблонного кода, и при этом уведомлять программиста в случае, если кто-то предоставляет слишком много аргументов (что хорошо по причинам, перечисленным в первой части ответа).
Что и почему было выбрано TypeError
: «Неверное количество аргументов» - это ошибка типа компиляции / несоответствие типа в статических языках. У нас нет проверки во время компиляции для таких вещей в Python, но это все еще своего рода «ошибка типа». Если (в Python, неофициальный) тип подписи говорит: «Я беру два аргумента», а вы предоставляете три, это, очевидно, является нарушением этого контракта. TypeError
не просто означает not isinstance(x, expected)
, как и многие другие темы, связанные с типизацией (просто подумайте о наследовании и "получает родительский материал" против "is-a parent"), это гораздо более широкое понятие.
Отредактируйте в ответ на вашу критику сравнения статической типизации: рассмотрение унарной функции, отличной от бинарной функции, - не просто ограничение системы статического типа. Это очень полезно даже в таких языках, как Python, поскольку они не настолько похожи, чтобы их можно было использовать «как если бы они ходили и крякали одинаково» (как при наборе утки) - их нельзя использовать одинаково. (Исключение, метапрограммирование, которое оборачивает функции абриритичности, обрабатывается операторами распаковки *
и **
.) Они случайно разделяют тот факт, что их можно вызывать, но они несовместимы, даже если встроенная объектная иерархия Python не создает многочисленные идентичные классы, которые отличаются только арностью и, следовательно, именем. type(f)
может сказать function
, но это не всегда конец истории.