Когда вы читаете документацию к некоторым функциям, вы видите, что в определении функции передаются косая черта (/) и звездочка (*). Зачем они нужны?
Зачем используются косая черта и звездочка?
Косая черта (/) и звездочка (*) используются для определения того, как должен передаваться аргумент при вызове функции.
Параметры с левой стороны от косой черты должны передаваться только как позиционные аргументы, в то время как параметры с правой стороны могут передаваться как позиционные или как именованные.
Звездочка указывает на то, что параметры справа от нее должны передаваться только как именованные, а параметры слева могут передаваться как позиционные или как именованные.


| Параметры слева | Символ | Параметры справа |
|---|---|---|
| Только позиционные аргументы | / | Или позиционные, или именованные аргументы |
| Или позиционные, или именованные аргументы | * | Только именованные аргументы |
Косая черта и звездочка в параметре функции
Вот простой пример, показывающий, что когда в определении функции появляются косая черта и звездочка, то параметры привязываются исключительно к позиционным или именованным аргументам.
# Normal Function
def func_params(x, y, /, *, z):
print(x, y, z)
Можно сделать вывод, что x и y — это исключительно позиционные параметры, а z — исключительно именованный. Давайте экспериментально проверим, связаны ли параметры только с позиционными и только с именованными аргументами.
params = func_params(2, y=3, z=4)
Параметр x передается как позиционный аргумент, а y и z — как именованные. При запуске кода будет получен следующий вывод:
Traceback (most recent call last):
...
params = func_params(2, y=3, z=4)
^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: func_params() got some positional-only arguments passed as keyword arguments: 'y'
Python выдает ошибку TypeError, указывая на то, что исключительно позиционный параметр (y), был задан в виде именованного аргумента. Если вы просто передадите y как позиционный аргумент, код не выдаст никаких ошибок.
# Normal Function
def func_params(x, y, /, *, z):
print(x, y, z)
# x & y passed as positional argument and z as a keyword argument
params = func_params(2, 3, z=4)
--------------------
2 3 4
Можно ли использовать звездочку перед косой чертой
Если вы используете и косую черту, и звездочку, то косая черта должна стоять перед звездочкой, иначе Python выдаст синтаксическую ошибку.
# Used asterisk before slash
def func_params(x, y, *, /, z):
print(x, y, z)
params = func_params(2, 3, z=4)
Код был изменен, и звездочка используется перед косой чертой. Запустив код, вы получите ошибку синтаксиса.
...
def func_params(x, y, *, /, z):
^
SyntaxError: / must be ahead of *
Логически вставка звездочки перед косой чертой не имеет смысла, потому что параметры справа от звездочки относятся только к именованным, а параметры слева от косой черты — только к позиционным.
Это не будет работать вообще. Вот пример, демонстрирующий эту ситуацию.
# Used asterisk before slash
def func_params(x, y, *, a, b, /, z):
print(x, y, a, b, z)
params = func_params(2, 3, a=5, b=6, z=4)
Параметры a и b находятся между звездочкой и косой чертой, поэтому неясно, являются ли они позиционными или исключительно именованными. Этот код все равно выдаст синтаксическую ошибку даже после передачи a и b в качестве именованных аргументов.
Использование в параметре функции или косой черты, или звездочки
Вы можете использовать косую черту и звездочку по отдельности, в зависимости от типа параметров, которые вам нужны. Вот пример, демонстрирующий использование только косой черты в определении функции.
def func_params(pos1, pos2, /, pos_or_kw):
print(pos1, pos2, pos_or_kw)
params = func_params(2, 3, pos_or_kw=4)
--------------------
2 3 4
Параметры pos1 и pos2 являются исключительно позиционными, а pos_or_kw — позиционным или именованным.
Аналогично, в определении функции можно использовать и только звездочку.
def func_params(pos_or_kw, *, kw1, kw2):
print(pos_or_kw, kw1, kw2)
params = func_params(4, kw1=3, kw2=2)
--------------------
4 3 2
Написание функции, принимающей только позиционные аргументы
Если вы хотите создать функцию или класс, принимающий только позиционные аргументы, добавьте косую черту в конце списка параметров.
# Function that takes only positional arguments
def prescription(med1, med2, med3, /):
print("Prescribed Meds:")
print(f"Med 1: {med1}")
print(f"Med 2: {med2}")
print(f"Med 3: {med3}")
prescription("Paracetamol", "Omeprazole", "Ibuprofen")
--------------------
Prescribed Meds:
Med 1: Paracetamol
Med 2: Omeprazole
Med 3: Ibuprofen
Функция prescription() принимает три аргумента: med1, med2 и med3. Вы видите, что в конце параметров стоит косая черта, которая делает их исключительно позиционными.
Если вы попытаетесь передать в функцию prescription() именованный аргумент, то получите ошибку.
prescription("Paracetamol", "Omeprazole", med3="Ibuprofen")
--------------------
Traceback (most recent call last):
...
prescription("Paracetamol", "Omeprazole", med3="Ibuprofen")
TypeError: prescription() got some positional-only arguments passed as keyword arguments: 'med3'
Написание функции, принимающей только именованные аргументы
Вы можете использовать звездочку в определении функции, чтобы сделать параметры в правой части исключительно именованными.
Если вам нужна функция, принимающая только именованные параметры, просто включите звездочку в начало списка параметров функции.
# Function that takes only keyword arguments
def prescription(*, med1, med2, med3):
print("Prescribed Meds:")
print(f"Med 1: {med1}")
print(f"Med 2: {med2}")
print(f"Med 3: {med3}")
prescription(med1="Paracetamol", med2="Omeprazole", med3="Ibuprofen")
-------------------
Prescribed Meds:
Med 1: Paracetamol
Med 2: Omeprazole
Med 3: Ibuprofen
Теперь функция prescription() принимает только аргументы с именами и не допускает позиционных аргументов.
Допустимые и недопустимые определения функций
Вот несколько допустимых определений функций, которые могут сочетаться с косой чертой и звездочкой. Источник.
def f(p1, p2, /, p_or_kw, *, kw): def f(p1, p2=None, /, p_or_kw=None, *, kw): def f(p1, p2=None, /, *, kw): def f(p1, p2=None, /): def f(p1, p2, /, p_or_kw): def f(p1, p2, /):
Скорее всего, вы знакомы с правилами определения позиционных и именованных параметров. В соответствии с этими правилами приведенные выше определения функций валидны.
Однако следующие определения функций считаются невалидными, поскольку они определены не в соответствии с правилами.
def f(p1, p2=None, /, p_or_kw, *, kw): def f(p1=None, p2, /, p_or_kw=None, *, kw): def f(p1=None, p2, /):
После определения параметра со значением по умолчанию все последующие параметры (для параметров после звездочки — опционально) должны быть тоже определены со значением по умолчанию, чтобы избежать двусмысленности в вызовах функций.
Заключение
Косая черта и звездочка определяют, как должен передаваться аргумент при вызове функции.
Косая черта в определении функции указывает на то, что параметры слева от нее должны рассматриваться только как позиционные.
Звездочка в определении функции указывает на то, что параметры справа от нее должны рассматриваться только как именованные.
В определении функции можно использовать как оба символа, так и какой-то один. Если вы используете и косую черту, и звездочку, косая черта должна идти перед звездочкой.
Источник: https://peps.python.org/pep-0570/
Перевод статьи “Why Slash and Asterisk Used in Function Definition”.

Пингбэк: Позиционные и именованные аргументы в функциях Python