Когда вы читаете документацию к некоторым функциям, вы видите, что в определении функции передаются косая черта (/) и звездочка (*). Зачем они нужны?
Зачем используются косая черта и звездочка?
Косая черта (/) и звездочка (*) используются для определения того, как должен передаваться аргумент при вызове функции.
Параметры с левой стороны от косой черты должны передаваться только как позиционные аргументы, в то время как параметры с правой стороны могут передаваться как позиционные или как именованные.
Звездочка указывает на то, что параметры справа от нее должны передаваться только как именованные, а параметры слева могут передаваться как позиционные или как именованные.
Параметры слева | Символ | Параметры справа |
---|---|---|
Только позиционные аргументы | / | Или позиционные, или именованные аргументы |
Или позиционные, или именованные аргументы | * | Только именованные аргументы |
Косая черта и звездочка в параметре функции
Вот простой пример, показывающий, что когда в определении функции появляются косая черта и звездочка, то параметры привязываются исключительно к позиционным или именованным аргументам.
# 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