В Python у функции можно объявлять параметры четырёх видов: позиционные, именованные (keyword), только позиционные (positional-only) и только именованные (keyword-only). Их различие влияет на способ передачи значений при вызове функции.
/ (Python 3.8+), нельзя задавать по имени.*, можно задать только по ключу.# Пример всех типов def func(a, b, /, c, *, d, e): print(a, b, c, d, e) func(1, 2, 3, d=4, e=5) # OK # func(a=1, b=2, 3, d=4, e=5) # Ошибка: a, b - только позиционные
SyntaxError или TypeError.*args собирает доп. позиционные; **kwargs — именованные.Чем различаются объявления функций:
def f(a, b, c): ... def f(a, b, c=1): ... def f(a, b=1, c=2): ... def f(a=1, b=2, c=3): ...
и правда ли, что все эти функции можно вызывать и с позиционными, и с ключевыми параметрами?
def f(a, b, c): нельзя вызвать с ключевыми только аргументами, потому что все можно передать как по позиции, так и по ключу, но все аргументы обязательны.def f(a, b, /, c):, то a и b можно только по позиции.def f(a, b, c=10): print(a, b, c) f(1, 2) # OK, c=10 по умолчанию f(a=1, b=2, c=3) # OK # А вот: def f(a, b, /, c=10): ... f(1, 2) # OK f(a=1, b=2, c=3) # Ошибка! a и b только позиционно
История
Разработчик реализовал функцию, которая по соглашению должна принимать параметры исключительно по имени: логирование со множеством параметров, часть из них опциональная. Но забыли объявить * — и пользователи случайно передавали параметры в разном порядке по позиции, что приводило к неправильному логированию и ошибкам, которые трудно отследить.
История
В проекте с REST API из-за неявного соглашения о порядке аргументов (использовали *args и не ограничивали параметры по имени) перестали работать запросы после внедрения новой версии клиента — потому что args сместились. Исправили введением явных * и указанием только именованных аргументов.
История
В большом корпоративном проекте функцию расширили новыми параметрами с дефолтными значениями, но из-за ошибочного вызова с позиционными значениями старый код начал подставлять значения в другие параметры, что вызвало некорректную обработку данных. Оказалось, что параметры нужно было делать только именованными.