AaronCoding
AaronCoding

Reputation: 168

How to force the default parameter in python

TLDR: I want to pass an argument to a function which forces the function to use it's default, as if I didn't supply any arguments.

For example

def foo(string = "DEFAULT PARAM"):
    print(string)

def bar(string = None):
    foo(string)

bar()            # Should print "DEFAULT PARAM", but instead prints None
bar("Hello!")    # Should print "Hello!"

I know there are a lot of workarounds like:

def bar(string = None):
    foo() if string is None else foo(string)

But I was hoping for something more elegant. Like some kind of default keyword I can set bar's default string to. Is that a thing?

Upvotes: 3

Views: 3332

Answers (4)

mgilson
mgilson

Reputation: 309919

You can't. I believe that there have been discussions about adding a new singleton to use in cases where None is an acceptable value to pass. To my knowledge, those proposals have always been shot down because python has plenty of singletons already:

NotImplemented
Ellipsis
None

Your proposed solution is what is typical with mutable default arguments so it also makes sense to use it for other cases as well (like this one). Obviously there are times when None is a reasonable value to pass -- In that case, choose another singleton or create your own (via object()).


Your final recourse (i.e. when you do not have control over the function and when you simply can't call the function without passing an argument) is to parse the default value from the function itself and pass that.

Obviously, this approach should be used sparingly :-)

Upvotes: 0

Alex Undefined
Alex Undefined

Reputation: 630

def foo(string = 'default'):
    print(string)

def bar(**kwargs):
    foo(**kwargs)

bar() # prints 'default'
bar(string = 'baz') # prints 'baz'

Upvotes: -1

wim
wim

Reputation: 362707

I have encountered this annoyance many times in Python (mostly when using argparse, which populates omitted options with null values instead of just omitting them from the namespace).

When you want to explicitly pass None as a value, and have it be treated the same as if it was just omitted completely, this is best:

def foo(string=None):
    if string is None:
        string = "DEFAULT PARAM"
    print(string)

def bar(string=None):
    foo(string)

The opposite annoyance is when None is a valid value, and you actually need to pass it explicitly sometimes. In that case, this is best:

sentinel = object()

def foo(arg=sentinel):
    if arg is sentinel:
        arg = "DEFAULT PARAM"
    print(arg)

def bar(arg=None):
    foo(arg)

Upvotes: 8

chepner
chepner

Reputation: 531165

No, there is no value that you can pass that will trigger the default value to be used in place of the passed value. Passing a value binds that value to the formal parameter, period.

Upvotes: 6

Related Questions