I have a need for functions with default arguments that have to be set at function runtime (such as empty lists, values derived from other arguments or data taken from the d
You can replace
baz = baz if baz else blar()
with
baz = baz or blar()
if you're still happy with just testing for falsy values instead of None
.
A quick&dirty example implementation of something that might work:
class DynDefault(object):
def __init__(self, callback):
self.callback = callback
def __call__(self):
return self.callback()
def dyn_default(func):
def wrapper(*args, **kw):
args = [arg() for arg in args if isinstance(arg, DynDefault) else arg]
for k, v in kw.items():
if isinstance(v, DynDefault):
kw[k] = v()
return func(*args, **kw)
return wrapper
@dyn_default
def foo(bar, baaz=DynDefault(blar)):
# problem solved
No, that's pretty much it. Usually you test for is None
so you can safely pass in falsey values like 0
or ""
etc.
def foo(bar, baz=None):
baz = baz if baz is not None else blar()
The old fashioned way is the two liner. Some people may prefer this
def foo(bar, baz=None):
if baz is None:
baz = blar()
You could do something like this:
def getArg():
try:
return arg
except NameError:
return 0
def foo(x, y=getArg):
y = y()
print(y)
foo(1) # Prints 0 (Default)
arg = 7 # Set by argparse?
foo(2) # Prints 7 (Dynamic global)
foo(3, lambda:9) # Prints 9 (Dynamic passed)