2

When a function I'm calling has a lot of parameters, and there's one I'd like to include conditionally, do I have to have two separate calls to the function, or is there someway to pass nothing (almost like None) so that I'm not passing in any argument for a particular parameter?

For example, I want to pass an argument for the parameter sixth sometimes, but other times I want to not pass anything for that parameter. This code works, but it feels like I'm duplicating more than I should have to.

The function I'm calling is in a third-party library, so I can't change how it handles the received arguments. If I pass in None for sixth, the function raises an exception. I need to either pass my 'IMPORTANT_VALUE' or not pass in anything.

What I'm doing currently:

def do_a_thing(stuff, special=False):

    if special:
        response = some.library.func(
            first=os.environ['first'],
            second=stuff['second'],
            third=stuff['third']
            fourth='Some Value',
            fifth=False,
            sixth='IMPORTANT_VALUE',
            seventh='example',
            eighth=True
        )
    else:
        response = some.library.func(
            first=os.environ['first'],
            second=stuff['second'],
            third=stuff['third']
            fourth='Some Value',
            fifth=False,
            seventh='example',
            eighth=True
        )

    return response

What I'd like to do:

def do_a_thing(stuff, special=False):
    special_value = 'IMPORTANT_VALUE' if special else EMPTY_VALUE

    response = some.library.func(
        first=os.environ['first'],
        second=stuff['second'],
        third=stuff['third']
        fourth='Some Value',
        fifth=False,
        sixth=special_value,
        seventh='example',
        eighth=True
    )

    return response
WhiteHotLoveTiger
  • 2,088
  • 3
  • 30
  • 41
  • The way to do this is look at `some.library.func` and see what the default value for the argument you want to omit is, then pass that in when you don't want the sixth argument. – kindall Feb 23 '18 at 15:57
  • 1
    _If I pass in None for sixth, the function raises an exception_ What is the exception? Does it give you any clues? – John Gordon Feb 23 '18 at 16:02
  • It returns an invalid parameter error when I pass in `None`. It wants only nothing passed in, or `str` values, and even then, only particular strings. The library function is a boto3 call to boto3.client('cognito-idp').admin_create_user(), but I was trying to keep the question more general. https://boto3.readthedocs.io/en/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.admin_create_user – WhiteHotLoveTiger Feb 23 '18 at 19:51

3 Answers3

7

One solution could be building a dict with values you want to pass to the function, modified depending on special value. Then use python unpacking to expand it as a list of named arguments to the function you want to call:

def do_a_thing(stuff, special=False):

    kwargs = dict(
        first=os.environ['first'],
        second=stuff['second'],
        third=stuff['third']
        fourth='Some Value',
        fifth=False,
        seventh='example',
        eighth=True
    )

    if special:
        kwargs['sixth'] = 'IMPORTANT_VALUE'

    return some.library.func(**kwargs)
Antwane
  • 20,760
  • 7
  • 51
  • 84
2

Since functions are first class objects, you can pass that function to a wrapper that will construct the params you want properly. This will make that piece of code reusable but also gives you more flexibility, like handling errors is needed.

def wrapper(some_library_func, special=False):
# you could have try catch here if needed. 
  kwards = {
    'first': os.environ['first'],
    'second': stuff['second'],
    'third': stuff['third'],
    'fourth': 'Some Value',
    'fifth': False,
    'seventh': 'example',
    'eighth': True
  }

  if special:
    kwards['sixth'] = 'IMPORTANT_VALUE'

  return some_library_func(**kwards)
randyjp
  • 1,084
  • 9
  • 8
-2

I don't see anything wrong with your way of doing it, using a function to define the variable. You should declare special_value in global scope, then include global special_value at the top of your function.

Levi Lesches
  • 1,508
  • 1
  • 13
  • 23
  • _I don't see anything wrong with your way of doing it_ Nothing wrong except that he said it doesn't work... – John Gordon Feb 23 '18 at 16:01
  • His second solution ("What I'd like to do...") looks fine and he didn't say it returned an error – Levi Lesches Feb 25 '18 at 19:44
  • Sorry I wasn't more clear. `EMPTY_VALUE` is a placeholder for a literal empty value of not passing anything. I don't know if there is such a thing in Python. – WhiteHotLoveTiger Feb 26 '18 at 13:56
  • 1
    I'm starting to realize the scope of the issue. I suggest finding the default value for this function (as you noted, you didn't make it), and supply it in the `else` part of your `do_a_thing` function – Levi Lesches Feb 26 '18 at 16:03