2

Is it possible to explicitly tell a function in python to use the default value of a parameter ?

For instance, if a function is defined as:

def foo(a=1, b=2, c=3):
    pass

I would like to call the function like:

foo(a=3, b=<USE-DEFAULT>, c=10)
                ^
                |

which should be equivalent to:

foo(a=3, c=10)

One usage example is if a function is used to instantiate an instance of a class:

class foo():
    def __init__(a=1, b=2, c=3):
       self.a = a
       self.b = b
       self.c = c

def create_foo(a=None, b=None, c=None):
    f = foo( <PASS ALL EXCEPT NONE> )

F = create_foo(a=10, c=30)
# Then F should have a=10, b=2, c=30

In this example, I would like to avoid defining default values multiple times.

Pedia
  • 1,432
  • 2
  • 11
  • 17
  • 2
    Why you want this? – mohammad May 11 '17 at 10:18
  • 6
    Simply ignoring it causes using default value! – mohammad May 11 '17 at 10:18
  • 1
    Don't pass the value, it will automatically use `default` value – akash karothiya May 11 '17 at 10:21
  • 2
    `foo(a=3, c=10)` would work fine. why do you explicitly want to specify the default value? – Akshay Apte May 11 '17 at 10:21
  • foo(a=321, b=2, c=199)...just use again the default value...as said it makes no sense in python! – Marco smdm May 11 '17 at 10:25
  • 1
    With the updated example this seems to be more a question of how to generically transfer arguments through multiple functions. I have updated my answer for this. – languitar May 11 '17 at 10:32
  • For future visitors, another use case that might lead you here: I recently wrote a script with some business methods that usually are called in a specific order and don't need any other actions performed in between - usually, not allways. So I implemented all business logic and also an api method that simply cals the business methods in the usual order but now I have to write the default values twice, right? Wrong! We could use None and check for it but it's ugly. Better use **kwargs so the api method simply hands over all given arguments and the business methods use default values as needed. – hajef Feb 18 '19 at 10:12

3 Answers3

3

Just call that functions as

foo(a=3, c=10)

Alternatively, you could use the following approach, which is e.g. necessary for lists, because default values are evaluated in the module scope:

def foo(a=None, b=None, c=None):
    local_a = a or "default"
    ...

foo(a=42, b=None, c=16)

None then encodes to use the default, if None is no valid option.

Finally, you could just defined the defaults as "constants":

DEFAULT_A = 42
DEFAULT_B = "foo"
DEFAULT_C = 17

def foo(a=DEFAULT_A, b=DEFAULT_B, c=DEFAULT_C):
    pass

foo(16, DEFAULT_B, 123)

But this is quite uncommon.

For you updated example, I would propose to use * and ** operators:

def create_foo(*args, **kwargs):
    f = foo(*args, **kwargs)

create_foo(42, b="non-default")

See this question for explanations how these operators work.

languitar
  • 6,554
  • 2
  • 37
  • 62
  • This doesn't "explicitly indicate usage of default value" – Sayse May 11 '17 at 10:22
  • As a function always has to evaluate all parameters, it must use the default. There is simply no other language-internal way of doing that. – languitar May 11 '17 at 10:22
  • Even the parenthesis are wrong ;) @Sayse: why do you want to mentioned again the default value? If so then you have to write the same...for instance b=2, but it makes no sense as above said – Marco smdm May 11 '17 at 10:23
  • Updated for the wrong parens. And another "hacky" solution. – languitar May 11 '17 at 10:26
2

If you don't use *args and **kwargs and subclassing there is no reason to explicitly call the defaults and as long as you are using only your own classes and you don't need mutual default arguments, you can just hand over the same values as the defaults - BUT if you are working with *args and **kwargs and the method to be called is from a super class, you might get problems with the MRO. (See this article for further information: https://www.python.org/download/releases/2.3/mro/)

The only way I know to prevent a(n at this moment unknown) super class to pass an argument to the class your calss extends is to call the method explicidly and than hand over only the arguments you want it to get.
I don't see another use case for an explicit default call.

hajef
  • 334
  • 2
  • 13
  • Note that, following this advice, you might cause the subclass that calls you as `super` to get trouble itself. MRO is a tricky thing in Python and you should either use super at all places of all classes or never. – hajef May 11 '17 at 14:04
0

When defining function, you can set the default value, so when you call the function you do not need to pass the default argument to the function.

def foo(a=1, b=<USE-DEFAULT>, c=3):
    print(b)

foo(a=3, c=10)

In above function foo, you are actually setting the default value for all arguments a, b, c

example:

>>> def foo(a=1, b=2, c=3):
...     print('a: {0}, b: {1}, c: {2}'.format(a, b, c))
... 
>>> foo(a=3, c=10)
a: 3, b: 2, c: 10
>>> foo()
a: 1, b: 2, c: 3
>>> foo(a=3)
a: 3, b: 2, c: 3
>>> foo(a=3, c=10, b=5)
a: 3, b: 5, c: 10
>>> 
JkShaw
  • 1,927
  • 2
  • 13
  • 14