0

I have a script which uses a required parameter and some optional. What would be the best way to call a function with these optional parameters?

Right now I have these if, but I'm pretty sure there must be a better way to handle this situation. Otherwise, what would I do if instead of 4 optional parameters they are 100 (bad practice, just for the example)? Use an if for each one?

def get_data(table, db='postgres', host='localhost', user='postgres', password=''):
....
....
....

kwargs = {}
if args.db:
    kwargs['db'] = args.db
if args.host:
    kwargs['host'] = args.host
if args.user:
    kwargs['user'] = args.user
if args.password:
    kwargs['password'] = args.password


data = get_data(args.table, **kwargs)
  • 2
    All those `if`s are doing is convert `args` to `kwargs`. Can't this be done with `**args`…? – deceze May 04 '18 at 12:08
  • @deceze args is the output of `argparse` `parse_args()`. If I try to use it directly it says `argument after ** must be a mapping, not Namespace`. –  May 04 '18 at 12:15
  • 1
    Use `get_data(**vars(args))`. – Aran-Fey May 04 '18 at 12:16
  • @Aran-Fey that's not right, unless OP specifies the same defaults in the argument parser as in `get_data`. OP doesn't want to override the function defaults. – Alex Hall May 04 '18 at 12:24
  • 1
    @AlexHall True I guess, but I interpreted the question as "what's a smarter way to turn the `args` object into a dict", and for that `vars` is absolutely sufficient. Filtering out `None` values afterwards is easy enough. I've added a relevant dupe, and here's a piece of code for the lazy: `get_data(**{k:v for k,v in vars(args).items() if v is not None})` – Aran-Fey May 04 '18 at 12:29

1 Answers1

1
for key in 'db host user password'.split():
    val = getattr(args, key)
    if val:
        kwargs[key] = val
Alex Hall
  • 34,833
  • 5
  • 57
  • 89