Есть ли способ передать необязательные параметры функции?

133

Есть ли в Python способ передать необязательные параметры функции при ее вызове, и в определении функции есть некоторый код, основанный на «только если передан необязательный параметр»

user1795998
источник

Ответы:

115

Документация Python 2, 7.6. Определения функций дают вам несколько способов определить, предоставил ли вызывающий необязательный параметр.

Во-первых, вы можете использовать специальный синтаксис формальных параметров *. Если в определении функции есть формальный параметр, которому предшествует единственный *, то Python заполняет этот параметр любыми позиционными параметрами, которые не соответствуют предшествующим формальным параметрам (в виде кортежа). Если определению функции предшествует формальный параметр **, то Python заполняет этот параметр любыми ключевыми параметрами, которые не совпадают с предшествующими формальными параметрами (как dict). Реализация функции может проверять содержимое этих параметров на предмет любых «необязательных параметров» нужного вам типа.

Например, вот функция , opt_funкоторая принимает два позиционных параметров x1и x2, и ищут другой ключевое слово параметр с именем «необязательно».

>>> def opt_fun(x1, x2, *positional_parameters, **keyword_parameters):
...     if ('optional' in keyword_parameters):
...         print 'optional parameter found, it is ', keyword_parameters['optional']
...     else:
...         print 'no optional parameter, sorry'
... 
>>> opt_fun(1, 2)
no optional parameter, sorry
>>> opt_fun(1,2, optional="yes")
optional parameter found, it is  yes
>>> opt_fun(1,2, another="yes")
no optional parameter, sorry

Во-вторых, вы можете указать значение параметра по умолчанию для некоторого значения, Noneкоторое вызывающий абонент никогда бы не использовал. Если параметр имеет это значение по умолчанию, вы знаете, что вызывающая сторона не указала параметр. Если параметр имеет значение, отличное от значения по умолчанию, вы знаете, что оно пришло от вызывающего.

Джим ДеланХант
источник
7
positional_parametersкортеж и keyword_parametersсловарь.
Cees Timmerman
Как питон отличает formal parameters preceded by * (как это называется?) От keyword parameter? Насколько я понял, параметры ключевого слова указываются с помощью =оператора в вызове функции (поэтому opt_fun(1,2, optional="yes")предоставляет аргумент ключевого слова «да» для функции, которая ожидает, но не обязательно требует, параметр option).
Минь Тран
С другой стороны, я понимал formal parameters preceded by * это просто как «аргументы, предоставленные вызывающей стороной, которые не соответствуют позиционным аргументам, предшествующим любым аргументам ключевого слова». Так , например, в opt_fun(1,2, "blah", 3.14, mykey="yes", myyear="2018"), "blah"и 3.14это forma arguments preceded by *потому , что между двумя позиционными аргументами и аргументом , который использует =знак. Полученный кортеж positional_parameterбудет двухтактный: ("blah", 3.14). Это верно?
Минь Тран
@MinhTran, вопросы в комментариях - не лучший способ получить ответ в Stack Overflow. Намного лучше нажать большую синюю кнопку «Задать вопрос» и написать свой запрос как «Вопрос», на который другие смогут «Ответить». Но чтобы помочь вам, а) обратите внимание, что я написал parameter"не parameters" для " preceded by *". Язык допускает только один *identifierпараметр в списке. б) прочтите docs.python.org/2/reference/… , в) прочтите docs.python.org/2/reference/expressions.html#calls . Извините, в этом комментарии не хватает символов.
Джим ДеЛаХант
81
def my_func(mandatory_arg, optional_arg=100):
    print(mandatory_arg, optional_arg)

http://docs.python.org/2/tutorial/controlflow.html#default-argument-values

Я считаю это более читаемым, чем использование **kwargs.

Чтобы определить, был ли вообще передан аргумент, я использую пользовательский служебный объект в качестве значения по умолчанию:

MISSING = object()

def func(arg=MISSING):
    if arg is MISSING:
        ...
warvariuc
источник
-Спасибо, есть ли способ указать значение этого параметра по умолчанию в качестве другой переменной в коде?
user1795998
да. default_value=100; def my_func(mandatory_argument, optional_argument_with_default_value=default_value): ...
warvariuc
Похоже, это показывает, как использовать необязательные параметры, но не как проверить, передан ли один из них, о чем спрашивает OP.
Mawg требует восстановить Монику
4
В большинстве случаев это более простое и понятное решение, чем у Джима. Если вы установите значение по умолчанию на None, вы можете проверить, был ли параметр передан или нет. Единственный случай, когда решение Джима лучше, - это если важно различать передачу None в качестве аргумента и отсутствие передачи аргумента вообще.
Арнон Аксельрод
19
def op(a=4,b=6):
    add = a+b
    print add

i)op() [o/p: will be (4+6)=10]
ii)op(99) [o/p: will be (99+6)=105]
iii)op(1,1) [o/p: will be (1+1)=2]
Note:
 If none or one parameter is passed the default passed parameter will be considered for the function. 
Sanyal
источник
1
Есть ли способ передать только второй параметр (b), а не первый (a)?
Djidiouf
4
@Djidiouf Да, естьop(b=2)
Юрг Мерлин Спаак
7

Если вы хотите присвоить параметру значение по умолчанию в (). как (x = 10). Но важно сначала обязательный аргумент, а затем значение по умолчанию.

например.

(у, х = 10)

но

(x = 10, y) неверно

Sumit
источник
Спасибо, есть ли способ указать значение этого параметра по умолчанию в качестве другой переменной в коде?
user1795998
Да, вы можете использовать то, что называется *arg **kargаргументами функции. поиск в гугле.
sumit
Похоже, это показывает, как использовать необязательные параметры, но не как проверить, передан ли один из них, о чем спрашивает OP.
Mawg требует восстановить Монику
2

Вы можете указать значение по умолчанию для необязательного аргумента с чем-то, что никогда не будет передаваться в функцию, и проверить его с помощью isоператора:

class _NO_DEFAULT:
    def __repr__(self):return "<no default>"
_NO_DEFAULT = _NO_DEFAULT()

def func(optional= _NO_DEFAULT):
    if optional is _NO_DEFAULT:
        print("the optional argument was not passed")
    else:
        print("the optional argument was:",optional)

тогда, пока вы этого не сделаете, func(_NO_DEFAULT)вы можете точно определить, был передан аргумент или нет, и, в отличие от принятого ответа, вам не нужно беспокоиться о побочных эффектах ** нотации:

# these two work the same as using **
func()
func(optional=1)

# the optional argument can be positional or keyword unlike using **
func(1) 

#this correctly raises an error where as it would need to be explicitly checked when using **
func(invalid_arg=7)
Тадг Макдональд-Дженсен
источник
Просто делай _NO_DEFAULT = object().
Аран-Фей
Две дополнительные строчки для лучшего самоанализа того стоят. Благодаря этому, если вы запустите, help(func)вы получите более четкое представление, как интерпретируется аргумент, если он не передан явно.
Tadhg McDonald-Jensen