0

This one should be simple. Say I have a function and I call some function from some package within my function. I want to customize passing arguments to the package of the function on whether the user has passed arguments to my function. Example code:

import SomePackage as sp

def myFunc(foo, bar, baz=None, xad=False):
    # some code to do some stuff...
    # then finally:
    if baz is not None:
        sp.someFunc(data=foo, method=bar, aux=baz)
    else:
        sp.someFunc(data=foo, method=bar)

Is there a way to replace the last 4 lines with just one neat Pythonic line? Something like:

def myFunc(foo, bar, baz=None, xad=False):
    # some code to do some stuff...
    # then finally:
    sp.someFunc(data=foo, method=bar, [aux=baz if baz is not None])
Kartik
  • 8,347
  • 39
  • 73
  • What's wrong with your first example? `if/else` statements are Pythonic. – Christian Dean Nov 17 '16 at 19:44
  • Why does it matter if you pass it? If baz is None, it will be exactly the same either way. – Daniel Roseman Nov 17 '16 at 19:44
  • maybe look into " * " -> http://stackoverflow.com/questions/1993727/expanding-tuples-into-arguments – ted Nov 17 '16 at 19:45
  • What do you mean "passing arguments to the package of the function"? – kindall Nov 17 '16 at 19:45
  • @DanielRoseman, cannot do that. The function from the package expects there to be a value if I pass something to `aux`. If `aux` ends up `None` I get an error. @leaf, 2 reasons: 1. to learn, 2. for code aesthetics – Kartik Nov 17 '16 at 19:46
  • 1
    @leaf repeating `sp.someFunc(data=foo, method=bar` violates DRY. – John Gordon Nov 17 '16 at 19:50
  • @VictorSmt, maybe with `eval` won't work just off the bat. It needs to be assigned to the right variable. Note that I am skipping other kwags between `method` and `aux`. Unless I list them all out to the default values, I get stuck. @kindall, apologize that it is unclear. I'll try to reword it. – Kartik Nov 17 '16 at 19:51
  • You could also check if the `baz`parameter is equal to `None` in the `someFunc` method. It would give you that neat 'one-liner' and would only be one if-statement in the called method. – TanguyH Nov 17 '16 at 20:05
  • @TanguyH, I did not write `someFunc`. It comes from a package I import in the program. – Kartik Nov 17 '16 at 21:02

1 Answers1

2

You can use argument unpacking to do this:

def func1(one, two, three):
    args = {"one": one, "two": two, "three": three}
    func2(*args)

def func2(one, two, three):
    print "one = %s, two = %s, three = %s" % (one, two, three)

if __name__ == "__main__":
    func1(one="does", two="this", three="work")

Example run:

python foo.py
one = does, two = this, three = work

You can of course modify args however you see fit before passing it on.

Jim Stewart
  • 16,964
  • 5
  • 69
  • 89
  • Fixed a typo where the original version was calling `func2` from main. – Jim Stewart Nov 17 '16 at 19:56
  • Ok, the point is `three` should not appear in the `args` if `three` in `func1` is `None`... – Kartik Nov 17 '16 at 19:56
  • 1
    You'll still need conditional logic to add/remove it from `args`. There's nothing un-Pythonic or unnecessarily-repetitive about your original code, and in fact the code in your question is about the cleanest way to write it, but this is a generic answer to customizing arguments before passing them on to another function. In the specific case from your question, you should stick with the conditional. – Jim Stewart Nov 17 '16 at 19:58
  • Clarity trumps brevity in almost any situation, but if you need to expand the use case to a bunch of arguments or some other complex logic, something like my answer here is appropriate. – Jim Stewart Nov 17 '16 at 20:01
  • Exactly, I have about 4 such arguments, and `elif`ing through them causes lots of repeating and ends up quite messy... – Kartik Nov 17 '16 at 20:05