map(lambda k,v: self._value_store.update(k=v) if self.keyword_check(k) == True else print('bad parameter'), kwargs.keys(),kwargs.value)
keyword_check(k)
returns a boolean value depending on if it is on a list or not.
The goal of this is to basically update the dictionary value of each parameter and value that is passed in using kwargs
but only if the parameter name exists on a predefined list.
I'm not looking to use a for loop to solve this.
The question I have is that the else
parameter seems to be mandatory, but i dont want it to do anything except go to the next iterable if the keyword verification returns either True
or False
. I tried adding pass after the else clause but Python doesn't like it. It works with what I placed else print('bad parameter')
but that is just a temporary solution. What can i use here to literally do/output nothing when it is False
?
CodePudding user response:
Note that this expression actually does nothing (it's the same as yours, except for a couple of corrections, but spread over a few lines for readability):
map(lambda k,v: self._value_store.update((k,v)) # k=v always sets key 'k'
if self.keyword_check(k) == True
else print('bad parameter'),
kwargs.keys(),
kwargs.values()
)
map
returns a generator. Only when you collect the values of the generator will it actually execute the side effect (self._value_store.update
). So to get it to actually update the object's internal value store, you'd need to do something like
list(map(lambda k,v: self._value_store.update((k,v))
if self.keyword_check(k) == True
else print('bad parameter'),
kwargs.keys(),
kwargs.values()
))
(You could replace list
with all
to avoid creating a useless list of None
s; all
will work here because {}.update()
always returns None
, but that's probably even worse programming style.)
In general, using map
only to produce a side effect is not usually good style, unless you really have a need for the execution of the side effects to be delayed (and in that case, some documentation is called for).
Instead, pass the generator to update
as its first argument; update
iterates over its first argument, so the generator will be fully evaluated. Also, the expression is somewhat simpler and (I think) easier to read:
self._value_store.update((k,v) for k,v in kwargs.items()
if self.keyword_check(k))
You might find an explicit loop is even more readable:
for k, v in kwargs.items():
if self.keyword_check(k):
self._value_store[k] = v
# Or, possibly faster (or possibly not):
for k in kwargs.keys():
if self.keyword_check(k):
self._value_store[k] = kwargs[k]
By the way, testing the value returned by a boolean function for equality with True
is also an anti-pattern (which is why I didn't do it above). It risks ignoring a value which passed the test, if the predicate might return a truthy value other than True
.
CodePudding user response:
As others already pointed out, your function should always return a value (I'll not argue this).
However, maybe what you want to achieve is this:
map(lambda k,v: self.keyword_check(k) and self._value_store.update(k=v), kwargs.keys(),kwargs.value)
Notice I use an simple and
operator instead of the ternary operator as you did.
Here, the method self._value_store.update(k=v)
is only called if self.keyword_check(k)
is True
. Which is what you're after (avoid the need of an else clause).
This happens thanks to short circuit evaluation: to evaluate an AND expression, if the first operator is False, the expression is False and the second operator doesn't need to be evaluated.
Of course, you should note that, if the first statament (self.keyword_check(k)
) is False
, then the return value will be False
as it should be (a value should exist).