What is the 'pythonic' way to implement a waterfall if-statement like situation like this, when it applies to kwargs
? I'm trying to avoid a situation where c=None
is added to kwargs
(because having c
in the kwargs
keys causes all sorts of problems downstream).
def run_something(**kwargs):
print(kwargs)
def func(a = None, b=None, c=None):
if a and b and c:
run_something(a=a,b=b,c=c)
elif a and b:
run_something(a=a,b=b)
elif a:
run_something(a=a)
else:
run_something()
I know the easy answer is that I could just do:
def func(**kwargs):
run_something(**kwargs)
however my particular use case doesn't make this easy
CodePudding user response:
First of all, instead of doing tests like if a:
I am guessing what you really want to do is only pass the a argument of it isn't None
so testing if a is not None:
will pass a value for a that is 0 or an empty string, i.e. anything other than the default. So this is what I would do:
def run_something(**kwargs):
print(kwargs)
def func(a = None, b=None, c=None):
d = {}
if a is not None:
d['a'] = a
if b is not None:
d['b'] = b
if c is not None:
d['c'] = c
run_something(**d)
func(c=7, b=4)
Prints:
{'b': 4, 'c': 7}
Note that the above handles any combination of passed arguments, which your "waterfall" if
statements do not. If you really want to test for any non-False value as in your original code, then of course you can do:
def run_something(**kwargs):
print(kwargs)
def func(a=None, b=None, c=None):
d = {}
if a:
d['a'] = a
if b:
d['b'] = b
if c:
d['c'] = c
run_something(**d)
func(c=7, b=4)
CodePudding user response:
You can do something like this:
def run_something(**kwargs):
print(kwargs)
def func(a=None, b=None, c=None):
kwargs = {"a": a, "b": b, "c": c}
run_something(**{key_word: arg for key_word, arg in kwargs.items() if arg is not None})
func() # {}
func("a") # {'a': 'a'}
func("a", "b") # {'a': 'a', 'b': 'b'}
func("a", "b", "c") # {'a': 'a', 'b': 'b', 'c': 'c'}
func(b="b") # {'b': 'b'}
func("a", c="c") # {'a': 'a', 'c': 'c'}
func(b="b", c="c") # {'b': 'b', 'c': 'c'}
func(c="c") # {'c': 'c'}
this will handle any combination of a b and c
I used dictionary comprehension. in case you don't know what it means you can check this out python dictionary comprehension
CodePudding user response:
Short and sweet:
def foo(a=None, b=None, c=None):
run_something(
**({ 'a': a } if a else {}),
**({ 'b': b } if b else {}),
**({ 'c': c } if c else {}),
)
Whether it’s ‘pythonic’, I will not say. Personally, I find it a meaningless notion, vague and ad-hoc at best and self-contradictory at worst.