Some data value use a basic type like str
or int
,
but not all str and int are valid values of that data value.
Enums can limit the possibilities to only a defined set of values.
Example:
Blood type is a string, but have a set of only 8 valid strings.
Don't exist a blood called 'randombloodtype'
but 'AB-'
is valid.
from enum import Enum
class BloodType(str, Enum):
A_negative = "A-"
B_negative = "B-"
AB_negative = "AB-"
O_negative = "O-"
A_positive = "A+"
B_positive = "B+"
AB_positive = "AB+"
O_positive = "O+"
assert "A-" in list(BloodType)
assert "O+" == BloodType.O_positive
So why not just use list?
The below code do the same as the above:
BLOOD_TYPE = [
"A-",
"B-",
"AB-",
"O-",
"A+",
"B+",
"AB+",
"O+",
]
assert "A-" in BLOOD_TYPE
But let us suppose we should make a new piece of code. Given the donor blood type, returns the list of allowed recipients.
from typing import List
def blood_type_can_donate_to(donor: str) -> List[str]:
_recipients = {
"A-": ["A-", "AB-", "A+", "AB+"],
"B-": ["B-", "AB-", "B+", "AB+"],
"AB-": ["AB-", "AB+"],
"O-": ["A-","B-", "AB-", "O-", "A+", "B+", "AB+", "0+"],
"A+": ["A+", "AB+"],
"B+": ["B+", "AB+"],
"AB+": ["AB+"],
"O+": ["A+", "B+", "AB+", "O+"]
}
return _recipients[donor]
And using enum:
from enum import Enum
from typing import List
class BloodType(str, Enum):
A_negative = "A-"
B_negative = "B-"
AB_negative = "AB-"
O_negative = "O-"
A_positive = "A+"
B_positive = "B+"
AB_positive = "AB+"
O_positive = "O+"
def blood_type_can_donate_to(donor: BloodType) -> List[BloodType]:
if donor == BloodType.A_negative:
return [
BloodType.A_negative,
BloodType.AB_negative,
BloodType.A_positive,
BloodType.AB_positive
]
elif donor == BloodType.B_negative:
return [
BloodType.B_negative,
BloodType.AB_negative,
BloodType.B_positive,
BloodType.AB_positive
]
elif donor == BloodType.AB_negative:
return [
BloodType.AB_negative,
BloodType.AB_positive
]
elif donor == BloodType.O_negative:
return list(BloodType)
elif donor == BloodType.A_positive:
return [
BloodType.A_positive,
BloodType.AB_positive
]
elif donor == BloodType.B_positive:
return [
BloodType.B_positive,
BloodType.AB_positive
]
elif donor == BloodType.AB_positive:
return [
BloodType.AB_positive
]
elif donor == BloodType.O_positive:
return [
BloodType.A_positive,
BloodType.B_positive,
BloodType.AB_positive,
BloodType.O_positive
]
The second one does exactly the same as the first one, but have some big advantages:
- Help you to avoiding mistakes.
- Help to code editor to warning if you make a mistake.
- Help to the next person to works in the code, avoid mistakes.
See the first version again: It has a typo error, a 0 instead of a O.
Top comments (2)
You polute you code with large functions and several IFs.
The besto solution, IMHO is to use objects instead of enums
Thank you for reading my post.
I wrote a version without using ifs, using the dict like in the first code block. But the code formatting in the final article don't looks goods, so i changed.
Python pattern matching can be a better solution too, but is too new. I think can confuse beginners.