Reputation: 8295
Let's say I have a function (called function
) that takes a boolean argument with default value of True
like def function(argument1 = True)
.
Now let's say I want to use this function, specifying its argument using the output of another function (resolveArg
) that checks for arguments in an existing infrastructure. This resolveArg
method is used generally and if it can find the argument value destined for a given function (e.g. function
), then it sets the function argument to it, otherwise it sets the argument to None
.
How can I get function
to use the default value of its argument if its argument is set to None
by this other function (resolveArg
)?
def resolveArg(argName = None):
if argName in self.conf._argdict:
return(self.conf._argdict[argName].value)
else:
return(None)
def function(argument1 = True)
if argument1 is True:
return(True)
elif argument1 is False:
return(False)
else:
raise(Exception)
function(argument1 = resolveArg("red"))
Upvotes: 2
Views: 192
Reputation: 5311
Probably you want to modify your implementation of function
little bit as follow:
def function(argument1 = None)
if argument1 is None:
argument1 = True
return argument1
If you want to understand more about default function argument as None, you may want to refer to my other SO answer
Upvotes: 0
Reputation: 20344
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.
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)
Upvotes: 1
Reputation: 6703
I have not seen this kind of problem before, so may be there is a way to improve your logic and omit this functionality.
However there is a way to do introspection of code in Python by using the module "inspect".
An example usage is:
>>> def a(q=5):
... if q is None:
... return dict(inspect.getmembers(a))['func_defaults'][0]
... return q
...
>>> a()
5
>>> a(None)
5
The problem with this is that "func_defaults" returns a list which is inconvenient in case you have multiple argument function and as a whole makes the procedure error prone.
Upvotes: 1
Reputation: 3026
One way would be to give the same behavior to yourfunction
if the argument is True
or None
.
def function(arg=True):
if arg in [True, None]:
do_stuff()
else:
do_something_else()
Upvotes: 0