Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Refactor a if-elif-block into a pythonic dictionary

I have a big if-elif-else block in my code like this

if counted == 2:
    score = None

elif counted == 1:
    score = (sum(values) - 3) / 6 * 100

elif counted == 0:
    score = (sum(values) - 4) / 8 * 100

else:
    raise Exception('Should not be reached!')

With python I assume there is a way to solve that with a dict using the counted values as keys. But what comes as items into that dict? The new case expression is not an option here. IMHO this wouldn’t be pythonic no matter that it’s now part of Python standard.

Approach A

# Approach A
mydict = {
    0: ((sum(values) - 4) / 8 * 100),
    1: ((sum(values) - 3) / 6 * 100),
    2: None
}

print(mydict)
print(mydict[counted])

The problem here is that all items are executed.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

{0: 4625.0, 1: 6183.333333333334, 2: None}

Approach B

mydict = {
    0: (lambda _: (sum(values) - 4) / 8 * 100),
    1: (lambda _: (sum(values) - 3) / 6 * 100),
    2: (lambda _: None)
}

print(mydict)
print(mydict[counted](None))

Here I have the fake argument I don’t need. But it seems to be mandatory when creating a lambda.

{0: <function <lambda> at 0x7ff8f3dce040>, 1: <function <lambda> at 0x7ff8f3b6a670>, 2: <function <lambda> at 0x7ff8f3b6a700>}

Is there a another way?

Full MWE

#!/usr/bin/env python3
import random

values = random.choices(range(100), k=10)
counted = random.choice(range(3))

print(f'counted={counted}')

if counted == 2:
    score = None

elif counted == 1:
    score = (sum(values) - 3) / 6 * 100

elif counted == 0:
    score = (sum(values) - 4) / 8 * 100

else:
    raise Exception('Should not be reached!')

print(f'score={score}')

# Approach A
mydict = {
    0: ((sum(values) - 4) / 8 * 100),
    1: ((sum(values) - 3) / 6 * 100),
    2: None
}

print(mydict)
print(mydict[counted])

# Approach B
mydict = {
    0: (lambda _: (sum(values) - 4) / 8 * 100),
    1: (lambda _: (sum(values) - 3) / 6 * 100),
    2: (lambda _: None)
}

print(mydict)
print(mydict[counted](None))

>Solution :

The lambdas without the arguments works. Just needs the :

import random


values = random.choices(range(100), k=10)

mydict = {
    0: lambda: (sum(values) - 4) / 8 * 100,
    1: lambda: (sum(values) - 3) / 6 * 100,
    2: lambda: None
}

counted = random.choice(range(3))
mydict[counted]()
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading