7

Under normal circumstances one calls a function with its default arguments by omitting those arguments. However if I'm generating arguments on the fly, omitting one isn't always easy or elegant. Is there a way to use a function's default argument explicitly? That is, to pass an argument which points back to the default argument.

So something like this except with ~use default~ replaced with something intelligent.

def function(arg='default'):
  print(arg)

arg_list= ['not_default', ~use default~ ]

for arg in arg_list:
  function(arg=arg)

# output:
# not_default
# default

I don't know if it's even possible and given the term "default argument" all my searches come up with is coders first tutorial. If this functionality is not supported that's ok too, I'd just like to know.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
user1492428
  • 145
  • 1
  • 8
  • I haven't tried this, but I think it should be possible to instantiate a [`partial` object](https://docs.python.org/3/library/functools.html#partial-objects) dynamically. Have a look at [`functools.partial`](https://docs.python.org/3/library/functools.html#functools.partial). – Selcuk Aug 28 '19 at 02:26
  • If you are generatimg arguments on the fly don't you have a value for all arguments? Why can't you just use them? – wwii Aug 28 '19 at 02:37
  • Does your target function have only 1 argument which can take many values? If you really need to dig at the target function and if you dont know them ahead of time or dont own that function, maybe check out **inspect** module. https://stackoverflow.com/questions/12627118/get-a-function-arguments-default-value – JL Peyret Aug 28 '19 at 05:06

2 Answers2

1

There is no general purpose way to omit an argument; you can specialize to particular functions by explicitly passing the appropriate default value, but otherwise, your only option is to fail to pass the argument.

The closest you could come is to replace your individual values with tuples or dicts that omit the relevant argument, then unpack them at call time. So for your example, you'd change arglist's definition to:

arg_list = [{'arg': 'not_default'}, {}]

then use it like so:

for arg in arg_list:
    function(**arg)

A slightly uglier approach is to use a sentinel when you don't want to pass the argument, use that in your arg_list, and test for it, e.g.:

USEDEFAULT = object()
arg_list = ['not_default', USEDEFAULT]

for arg in arg_list:
    if arg is USEDEFAULT:
        function()
    else:
        function(arg=arg)

Obviously a bit less clean, but possibly more appropriate for specific use cases.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
1

Unfortunately there is no such feature in Python. There are hackarounds, but they're not very likable.

The simple and popular pattern is to move the default into the function body:

def function(arg=None):
    if arg is None:
        arg = 'default'
    ...

Now you can either omit the argument or pass arg=None explicitly to take on the default value.

wim
  • 338,267
  • 99
  • 616
  • 750