Using 'if', 'elif', and 'else' is not bad if it is done efficiently. But in general, the answer to your question would really depend upon individual circumstances.
Having said that, however, one way to do it would be to put your conditions inside a dict
(as highlighted by yourself in the tags).
Here are a few examples:
As a dict
:
conditions = {
1: 'One',
2: 'Two',
3: 'Three',
4: 'Four',
5: lambda x: x**2 # Can be substituted with actual functions defined elsewhere.
}
x = 3
if x in conditions.keys():
print(conditions[x])
returns:
Three
or in the case of a function:
x = 5
if x in conditions.keys():
func = conditions[x]
print(func(x))
returns:
25
Using a function to resemble switch...case
:
To make it even clearer, and have something like a switch...case
statement, you can do this:
def switch(case):
conditions = {
1: 'One',
2: 'Two',
3: 'Three',
4: 'Four',
5: lambda x: x**2
}
return condition[case] if case in conditions else False
It is ran like so:
>>> print(switch(2))
2
or for a non-existent items:
>>> print(switch(6))
False
Implementation on your example:
switch...case
function decorator (wrapper)
So to address the example you have added, we can do as follows:
First we need a general switch/case decorator:
def switch_case(switch):
def switcher(func):
def case(case):
return switch[case](case) if case in switch else None
return case
return switcher
Then we need a dictionary of our conditions, which are the one given in your example:
# Define the conditions in a dict.
conditions = {
'd': lambda x: True if 'd' else False, # You can say: True if 'a' or 'b' else False
'c': lambda x: True if 'c' else False
}
Now we Create a decorated switch-case function based on your conditions:
@switch_case(conditions)
def my_conditions(case):
return case
Then we specify the elements, or read them from a file, database or anything:
# Elements to be tested as string.
# It can be any flattened (not nested) iterable (str, tuple, list, numpy.array, etc.)
myDict = {'a': ['b', 'c'], 'b': ['c', 'd']}
elements = sum(myDict.values(), []) # Returns a flattened lists of values.
Evaluate the elements based on the conditions (generator object).
verdicts = map(my_conditions, elements)
Match the elements to the corresponding evaluation results (generator object).
status = zip(elements, verdicts)
Now we can positively regulate the outputs (discard None
vlues) and create a dict
in which the keys are the elements, and the values are the status of their conditions.
passed = {key+'flag': val for key, val in status if val is not None}
print(passed)
# output: {'cflag': True, 'dflag': True}
Add as variables to the namespace
At this point, you can use the dict as is; however, if you insist on adding it to the namespace, here is how:
# Rename values and add them to the name space.
locals().update(passed)
Test
Finally, let's test and ensure the values exist in the local namespace (notice that we haven't implemented any of these names before). So, if the condition returned a True
value for the particular character in the sequence, a variable would have been created:
>>> print(dflag) # We had 'd' in `myDict` values.
True
On the other had, if the condition returned None
, there will be no value in the namespace.
>>> print(aflag) # We didn't have 'a' in `myDict` values.
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-25-26f7e9594747> in <module>()
24
---> 25 print(aflag)
NameError: name 'aflag' is not defined
Note: Under the existing structure, if the condition returns False
, a variable will be created in the namespace and assigned a value of False
.
Hope this helps.