137

Is there a way in Python to pass optional parameters to a function while calling it and in the function definition have some code based on "only if the optional parameter is passed"

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
user1795998
  • 4,937
  • 7
  • 23
  • 23

5 Answers5

116

The Python 2 documentation, 7.6. Function definitions gives you a couple of ways to detect whether a caller supplied an optional parameter.

First, you can use special formal parameter syntax *. If the function definition has a formal parameter preceded by a single *, then Python populates that parameter with any positional parameters that aren't matched by preceding formal parameters (as a tuple). If the function definition has a formal parameter preceded by **, then Python populates that parameter with any keyword parameters that aren't matched by preceding formal parameters (as a dict). The function's implementation can check the contents of these parameters for any "optional parameters" of the sort you want.

For instance, here's a function opt_fun which takes two positional parameters x1 and x2, and looks for another keyword parameter named "optional".

>>> 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

Second, you can supply a default parameter value of some value like None which a caller would never use. If the parameter has this default value, you know the caller did not specify the parameter. If the parameter has a non-default value, you know it came from the caller.

Jim DeLaHunt
  • 10,960
  • 3
  • 45
  • 74
  • 7
    `positional_parameters` is a tuple, and `keyword_parameters` a dictionary. – Cees Timmerman Jan 08 '16 at 16:31
  • How does python distinguish `formal parameters preceded by * ` (what is this called?) from a `keyword parameter`? As I understood it, keyword parameters are specified using the `=` operator in the function call (so `opt_fun(1,2, optional="yes")` provides a keyword argument "yes" for a function that anticipates, but doesn't necessarily require, the parameter `option`). – Minh Tran Feb 05 '18 at 18:59
  • On the other hand, I understood `formal parameters preceded by * ` as simply "the caller-provided arguments that doesn't correspond to positional arguments that goes before any keyword arguments". For example, in `opt_fun(1,2, "blah", 3.14, mykey="yes", myyear="2018")`, `"blah"` and `3.14` are `forma arguments preceded by *` because it's in between the two positional arguments and the argument that uses the `=` sign. The resulting tuple `positional_parameter` would be the duple: `("blah", 3.14)`. Is this correct? – Minh Tran Feb 05 '18 at 19:02
  • @MinhTran, questions in comments are not the best way to get an answer in Stack Overflow. It's far better to click the big blue "Ask Question" button, and write your request as a "Question" which others can "Answer". But to help you, a) note I wrote "`parameter`" not "`parameters`" for "`preceded by *`". The language allows for only one `*identifier` in the parameter list. b) read https://docs.python.org/2/reference/compound_stmts.html#function-definitions, c) read https://docs.python.org/2/reference/expressions.html#calls . Sorry, running out of characters permitted in this comment. – Jim DeLaHunt Feb 06 '18 at 19:19
83
def my_func(mandatory_arg, optional_arg=100):
    print(mandatory_arg, optional_arg)

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

I find this more readable than using **kwargs.

To determine if an argument was passed at all, I use a custom utility object as the default value:

MISSING = object()

def func(arg=MISSING):
    if arg is MISSING:
        ...
warvariuc
  • 57,116
  • 41
  • 173
  • 227
  • -Thanks,is there a way to specify the default value of this parameter as another variable in the code? – user1795998 Dec 24 '12 at 07:00
  • yes. `default_value=100; def my_func(mandatory_argument, optional_argument_with_default_value=default_value): ...` – warvariuc Dec 24 '12 at 07:21
  • This appears to show how to use optional parameters, but not how to test if one is passed,which is what the OP is asking. – Mawg says reinstate Monica Mar 07 '16 at 10:38
  • 4
    In most cases this is the simpler and more straightforwad solution than Jim's. If you set the default value to None then you can check if the parameter was passed or not. The only case where Jim's solution is better is if it's important to distinguish between passing None as the argument and not passing an argument at all. – Arnon Axelrod Sep 05 '16 at 12:28
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
  • 864
  • 10
  • 22
7

If you want give some default value to a parameter assign value in (). like (x =10). But important is first should compulsory argument then default value.

eg.

(y, x =10)

but

(x=10, y) is wrong

sumit
  • 112
  • 6
2

You can specify a default value for the optional argument with something that would never passed to the function and check it with the is operator:

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)

then as long as you do not do func(_NO_DEFAULT) you can be accurately detect whether the argument was passed or not, and unlike the accepted answer you don't have to worry about side effects of ** notation:

# 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)
Tadhg McDonald-Jensen
  • 20,699
  • 5
  • 35
  • 59