2

Is there a way pass arguments conditionally in Python (I use Python 2.7)?

As an example, this code gives 2 or 3 arguments depending if the 3rd argument exists in a dictionary.

if "arg3" in my_dict:
    my_method(
        my_dict[arg1],
        my_dict[arg2],
        my_dict[arg3],
    )
else:
    my_method(
        my_dict[arg1],
        my_dict[arg2],
    )

I think it looks redundant to write it this way. I've seen some info on argparse, which I think would look like this:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument(my_dict[arg1])
parser.add_argument(my_dict[arg2])
if arg3 in my_dict:
    parser.add_argument(my_dict[arg3])
args = parser.parse_args()

my_method(args)

I don't really like this method either, as it needs an import and is hard to read.

Is there a way to do something like:

my_method(
    my_dict[arg1],
    my_dict[arg2],
    my_dict[arg3] if arg3 in my_dict,
)

Or any other way I am missing, that would be simple and clean?

David Gourde
  • 3,709
  • 2
  • 31
  • 65

4 Answers4

6

Assuming that your method signature is

def my_method(arg1=None, arg2=None, arg3=None):
    print ('arg1',arg1,'arg2',arg2,'arg3',arg3)

Then simply replace all those if/else blocks with

my_method(**dictionary)

For example

 d = {'arg3':11, 'arg2':22, 'arg1':3}

the above will produce

arg1 3 arg2 22 arg3 11

This behaviour is brought to by **kwargs there are quite a few good tutorials on it on the web. Here's one from digial ocean (I am not affiliated)

e4c5
  • 52,766
  • 11
  • 101
  • 134
  • how does this work given that `dictionaries` are not ordered? – Ma0 May 24 '17 at 15:24
  • That is the nature of kwargs – e4c5 May 24 '17 at 15:26
  • 1
    @Ev.Kounis It depends on the keyword arguments having the same names as the `dict` keys, in which case the order in which you provide the keyword arguments is irrelevant. This answer greatly depends on how `my_method` is defined, though. – chepner May 24 '17 at 15:27
  • Oh I see.. So the function variables have to be the same as the dictionary keys. nice! – Ma0 May 24 '17 at 15:27
  • I like your answer a lot, and it fits my question, but actually I also have arguments that are from outside of `my_dict` as well in the call, so this solution would not work for me, while the `.get(arg3, None)` will always work. – David Gourde May 25 '17 at 18:49
2

You can call it like that:

my_method(my_dict[arg1], my_dict[arg2], my_dict.get(arg3, None))

You might want to change the my_method to adapt for this; maybe something like def my_method(*args):.

For more info on the .get() dictionary method take a look at this.

This solution is definitely uglier (acc to the Pythonic standards of beauty) than the one provided by @e4c5 but does not require the function variables to have the same name as the dictionary keys.

Ma0
  • 15,057
  • 4
  • 35
  • 65
0

Both @Ev.Kounis and @e4c5 provide good answers. As far the attempt you made in the question, you are only missing a valid conditional expression.

my_method(
    my_dict[arg1],
    my_dict[arg2],
    my_dict[arg3] if arg3 in my_dict else None,
)

which is, practically speaking, the same as @Ev.Kounis proposed.

chepner
  • 497,756
  • 71
  • 530
  • 681
0

As an alternative, I would consider changing my_method to take in a dict if you know that you will be passing in a dict each time.

def my_method(d):
    a1 = d[arg1]
    a2 = d[arg2]
    a3 = d[arg3] if 'arg3' in d else None
    ...

Otherwise, the other answers are also valid.

Dennis Ye
  • 11
  • 1
  • 3