Caveat
You asked for a "good way to get a function to use its default value for an argument when the argument is specified as None in Python?"
I would argue that there isn't a good way, because it's not a good thing to do. This is a risky thing to do - it can mask nasty error cases where you might reasonably want to detect the fact that None
was passed in where you expected a value. Debugging where this technique is used extensively could be horrible. Use with extreme caution.
Possible method
I'm guessing you want a generic solution that will work for more functions than the one you offer as an example. In the example case - you would be easiest to simply test for None
in the argument value and replace it if necessary.
You could write a decorator to do the general case, that will use the inspect toolbox to work out the argument values across the list of arguments with default values and replace them if they are None
.
The code below demonstrates the idea with some simple test cases - this will work, but only for functions with simple arguments (not *args, **kwargs
) as currently constituted. It could be enhanced to cover those cases. It safely treats arguments without defaults as usual.
Python Fiddle
import inspect
def none2defaultdecorator(thisfunc):
(specargs, _, _, defaults) = inspect.getargspec(thisfunc)
def wrappedfunc(*instargs):
callargs = inspect.getcallargs(thisfunc, *instargs)
if len(specargs) != len(callargs):
print "Strange - different argument count in this call to those in spec"
print specargs
print callargs
for i,argname in enumerate(specargs[-len(defaults):]):
try:
if callargs[argname] == None:
callargs[argname] = defaults[i]
except KeyError:
# no local value for this argument - it will get the default anyway
pass
return thisfunc(**callargs)
return wrappedfunc
#Decorate the funtion with the "None replacer". Comment this out to see difference
@none2defaultdecorator
def test(binarg = True, myint = 5):
if binarg == True:
print "Got binarg == true"
elif binarg == False:
print "Got binarg == false"
else:
print "Didn't understand this argument - binarg == ", binarg
print "Argument values - binarg:",binarg,"; myint:",myint
test()
test(False)
test(True)
test(None)
test(None, None)