Reputation: 168
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
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
Reputation: 630
def foo(string = 'default'):
print(string)
def bar(**kwargs):
foo(**kwargs)
bar() # prints 'default'
bar(string = 'baz') # prints 'baz'
Upvotes: -1
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
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