Skip to content

Commit 90bcbc6

Browse files
mohanrajanrcmccandless
authored andcommitted
Python Concept Exercise enums
Pre concept exercise re-format.
1 parent c603e8c commit 90bcbc6

File tree

9 files changed

+489
-0
lines changed

9 files changed

+489
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
In Python, an enum is a set of names that are bound to unique `literal`, or `constant` values. Enums are defined the way classes are defined in python.
2+
3+
```python
4+
class Color(enum.Enum):
5+
RED = 1
6+
GREEN = 2
7+
```
8+
9+
Note that the values of the enum members can be even not int types such as str, tuple, float etc.
10+
11+
```python
12+
class Color(enum.Enum):
13+
RED = 'red'
14+
GREEN = 'green'
15+
```
16+
17+
Enums can also be created via Functional API.
18+
19+
```python
20+
Animal = Enum('Animal', 'ANT BEE CAT DOG')
21+
list(Animal)
22+
#=> [<Animal.ANT: 1>, <Animal.BEE: 2>, <Animal.CAT: 3>, <Animal.DOG: 4>]
23+
```
24+
25+
When you assign the same value to 2 members in an enum, the latter assigned member will be an alais to the formed one.
26+
27+
```python
28+
class Color(enum.Enum):
29+
RED = 1
30+
GREEN = 2
31+
ALAIS_OF_RED = 1
32+
Color.ALAIS_OF_RED
33+
#=> Color.RED
34+
```
35+
36+
You can iterate through all the members of the enum by 2 ways.
37+
38+
```python
39+
for member in Color
40+
print((member.name, member.value))
41+
#=> (RED, 1)
42+
#=> (GREEN, 2)
43+
44+
# __members__.items() helps you to loop through alias as well
45+
for member in Color.__members__.items():
46+
print(member)
47+
#=>('RED', <Color.RED: 1>)
48+
#=>('GREEN', <Color.GREEN: 2>)
49+
#=>('ALAIS_OF_RED', <Color.RED: 1>)
50+
```
51+
52+
You can check and compare enum members by using the (identity)`is` or `is not` operators. We can also use the `==` or `!=` operator.
53+
54+
```python
55+
a = Color.RED
56+
57+
a is Color.RED
58+
#=> True
59+
60+
a == Color.RED
61+
#=> True
62+
```
63+
64+
If you do not want to assign any value to the enum members you can use the `auto()` function
65+
66+
```python
67+
class Shapes(Enum):
68+
CIRCLE = auto()
69+
SQUARE = auto()
70+
OVAL = auto()
71+
```
72+
73+
If you do not want any aliases, and want to keep the members of the enum unique. you can use the `@unique` decorator.
74+
75+
```python
76+
@unique
77+
class Shapes(Enum):
78+
CIRCLE = 1
79+
SQUARE = 2
80+
TRIANGLE = 1
81+
#=> ValueError: duplicate values found in <enum 'shapes'="">: TRIANGLE -> CIRCLE
82+
```
83+
84+
There are various subclasses available for enum, such as IntEnum, etc. which allows only Int values.They can also be created by us manually.
85+
86+
```python
87+
class IntEnum(int, Enum):
88+
pass
89+
```
90+
91+
The same can be done for StrEnum and others etc. ( with the help of Mixins.)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## General
2+
3+
- [Python Docs: Enum](https://docs.python.org/3/library/enum.html)
4+
5+
## 1. Parse log level
6+
7+
- You need to use string splits to split the log message to multiple parts.
8+
- Once you have the required part of the string split you can use LogLevel(`string`) to return
9+
10+
## 2. Support unknown log level
11+
12+
- You need to first check if the value is in the LogLevel enum before calling LogLevel(`string`) and return.
13+
14+
## 3. Convert log line to short format
15+
16+
- You need to do an if else with all the members of the LogLevel and return the String along with the int value as per the given format. ( You need to use a `==` operator )
17+
18+
## 4. Create an Alias
19+
20+
- You just have to return the newly created alias value to the function output.
21+
22+
## 5. All Member Names and Values
23+
24+
- You need to iterate over all the members in the enum and return a tuple containing (member.name, member.value) in a list.
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
In this exercise you'll be processing log-lines.
2+
3+
Each log line is a string formatted as follows: `"[<LVL>]: <MESSAGE>"`.
4+
5+
These are the different log levels:
6+
7+
- `TRC` (trace)
8+
- `DBG` (debug)
9+
- `INF` (info)
10+
- `WRN` (warning)
11+
- `ERR` (error)
12+
- `FTL` (fatal)
13+
14+
You have three tasks.
15+
16+
## 1. Parse log level
17+
18+
Define a `LogLevel` enum that has six elements corresponding to the above log levels.
19+
20+
- `Trace`
21+
- `Debug`
22+
- `Info`
23+
- `Warning`
24+
- `Error`
25+
- `Fatal`
26+
27+
Defind the `parse_log_level` function which will take the 1 parameter, the log message. Return the Type of Log Level the log message belongs to.
28+
29+
Note: The `LogLevel` enum has to be defined on top of the file (outside the function).
30+
31+
```python
32+
parse_log_level("[INF]: File deleted")
33+
#=> LogLevel.Info
34+
```
35+
36+
## 2. Support unknown log level
37+
38+
Unfortunately, occasionally some log lines have an unknown log level. To gracefully handle these log lines, add an `Unknown` element to the `LogLevel` enum which should be returned when parsing an unknown log level:
39+
40+
```python
41+
parse_log_level("[XYZ]: Overly specific, out of context message")
42+
#=> LogLevel.Unknown
43+
```
44+
45+
## 3. Convert log line to short format
46+
47+
The log level of a log line is quite verbose. To reduce the disk space needed to store the log lines, a short format is developed: `"[<ENCODED_LEVEL>]:<MESSAGE>"`.
48+
49+
The encoded log level is simple mapping of a log level to a number:
50+
51+
- `Trace` - `0`
52+
- `Debug` - `1`
53+
- `Info` - `4`
54+
- `Warning` - `5`
55+
- `Error` - `6`
56+
- `Fatal` - `7`
57+
- `Unknown` - `42`
58+
59+
Define the `convert_to_short_log()` which takes 2 parameters.
60+
61+
1. Log level - The Log level of the log sent. ex: LogLevel.Error
62+
2. Log Message
63+
64+
```python
65+
convert_to_short_log(LogLevel.Error, "Stack overflow")
66+
# => "6:Stack overflow"
67+
```
68+
69+
## 4. Create an Alais
70+
71+
It looks like the user has created logs for `LogLevel.Warn` instead of `LogLevel.Warning`. Create an `alias` for `LogLevel.Warning` and return the alias name. This can be done on the same enum class you have defined at the top of the file.
72+
73+
Note: Both the LogLevels should point to same value. ie: LogLevel.Warning = "WRN" & LogLevel.Warn = "WRN"
74+
75+
```python
76+
return_alias()
77+
#=> LogLevel.Warn
78+
return_alias() == LogLevel.Warning
79+
#=> True
80+
```
81+
82+
## 5. All Member Names and Values
83+
84+
Define the function `return_members()` that will take 1 parameter.
85+
86+
1. This parameter will take a randomly created enum.
87+
88+
You should return the (name, value) in tuple format of all the members in a list.
89+
90+
```python
91+
92+
class Color(enum.Enum):
93+
RED = 'red'
94+
GREEN = 'green'
95+
96+
return_members(Color)
97+
#=> [('RED', 'red'), ('GREEN', 'green')]
98+
```
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
In Python, an enum is a set of names that are bound to unique `literal`, or `constant` values. Enums are defined the way classes are defined in python.
2+
3+
```python
4+
class Color(enum.Enum):
5+
RED = 1
6+
GREEN = 2
7+
```
8+
9+
Note that the values of the enum members can be even not int types such as str, tuple, float etc.
10+
11+
```python
12+
class Color(enum.Enum):
13+
RED = 'red'
14+
GREEN = 'green'
15+
```
16+
17+
Enums can also be created via Functional API.
18+
19+
```python
20+
Animal = Enum('Animal', 'ANT BEE CAT DOG')
21+
list(Animal)
22+
#=> [<Animal.ANT: 1>, <Animal.BEE: 2>, <Animal.CAT: 3>, <Animal.DOG: 4>]
23+
```
24+
25+
When you assign the same value to 2 members in an enum, the latter assigned member will be an alais to the formed one.
26+
27+
```python
28+
class Color(enum.Enum):
29+
RED = 1
30+
GREEN = 2
31+
ALAIS_OF_RED = 1
32+
Color.ALAIS_OF_RED
33+
#=> Color.RED
34+
```
35+
36+
You can iterate through all the members of the enum by 2 ways.
37+
38+
```python
39+
for member in Color
40+
print((member.name, member.value))
41+
#=> (RED, 1)
42+
#=> (GREEN, 2)
43+
44+
# __members__.items() helps you to loop through alias as well
45+
for member in Color.__members__.items():
46+
print(member)
47+
#=>('RED', <Color.RED: 1>)
48+
#=>('GREEN', <Color.GREEN: 2>)
49+
#=>('ALAIS_OF_RED', <Color.RED: 1>)
50+
```
51+
52+
You can check and compare enum members by using the (identity)`is` or `is not` operators. We can also use the `==` or `!=` operator.
53+
54+
```python
55+
a = Color.RED
56+
57+
a is Color.RED
58+
#=> True
59+
60+
a == Color.RED
61+
#=> True
62+
```
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"authors": [
3+
{
4+
"github_username": "mohanrajanr",
5+
"exercism_username": "mohanrajanr"
6+
}
7+
],
8+
"forked_from": ["csharp/enums"]
9+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
## Goal
2+
3+
The goal of this exercise is to teach the student how Enums ([Enumerations](https://en.wikipedia.org/wiki/Enumerated_type)) are implemented & used in Python. We will teach this through Pythons Enum class/type.
4+
5+
## Learning objectives
6+
7+
- What is an enumeration / enum is, and why they are needed/wanted in Python?
8+
- Understand the nomenclature (naming) used in reference to enums (e.g. enumeration/enum, enum members, enum member names, and enum member values)
9+
- Understand that enumeration members are functionally constants (and therefore should be formatted as such)
10+
- How Enums are different from other, more generic Python classes.
11+
- How to create various Enums
12+
- By using the class syntax by importing & subclassing Enum.
13+
- By using the Enum Functional API
14+
- By defining enum members with values that include non-int types (like str, tuple, float etc.)
15+
- Using the auto() function to automatically assign integer values to members when exact value types are unimportant/not needed.
16+
- Creating member aliases by assigning the same value to different names (two different names can have the same value; the second name defined becomes an alias of the first)
17+
- Using the class decorator @enum.unique to prevent member aliases and enforce that member values be unique.
18+
- How to use an enumeration and enumeration members in other functions/code
19+
- Enum members are iterable in member definition order, but iteration will not include aliases.
20+
- An ordered mapping of names to members can be retrieved via **members**.items()
21+
- enumeration members are compared by identity, using the is/is not keywords
22+
- Ordered comparison (<, >, <=, '>=) between enumeration valuesis not supported, and will throw aTypeError`.
23+
- Equality/inequality comparison is defined, and == and != can be used.
24+
- Comparisons between enumeration values and non-enumeration values will always return False
25+
26+
## Out of scope
27+
28+
- Flag enum subtype (perhaps better as an advanced exercise that includes bitwise operations)
29+
- IntEnum and IntFlag subtypes (since they break the semantic promises of an enum by being comparable to int)
30+
- mixins & multiple inheritance for the creation of Enums
31+
- using **new**() to customize the value of an enum member (better for an advanced/extended enum exercise)
32+
- omitting values
33+
- subclassing an "empty" pre-defined enum
34+
- customization of auto()
35+
- Pickling
36+
37+
## Concepts
38+
39+
- enumeration, enums
40+
41+
## Prerequisites
42+
43+
- `decorators, @`
44+
- `__init__()`
45+
- `classes, OOP`
46+
- `inheritance`
47+
- `iteration`
48+
- `iterables`
49+
- `dunder methods`
50+
- `comparisons`
51+
- `rich comparisons`
52+
- `class attributes`
53+
- `importing`
54+
- `aliasing`
55+
- `dicts, dict methods (specifically dict.items())`
56+
- `mapping types`
57+
- `immutable, immutability`
58+
- `class properties`
59+
60+
## Resources
61+
62+
- [Exercism v3 C# Enums concept exercise](https://github.com/exercism/v3/tree/master/languages/csharp/exercises/concept/enums)
63+
- [Python Docs: Enum](https://docs.python.org/3/library/enum.html)
64+
- [Enum - Mouse vs. Python](https://www.blog.pythonlibrary.org/2018/03/20/python-3-an-intro-to-enumerations/)
65+
- [Why you should use more enums in Python - Florian Dahlitz](https://florian-dahlitz.de/blog/why-you-should-use-more-enums-in-python)
66+
- [Python Docs: How are Enums Different?](https://docs.python.org/3/library/enum.html#how-are-enums-different)
67+
- [Python Docs: The Enum Functional API](https://docs.python.org/3/library/enum.html#functional-api)
68+
- [Stack Overflow: Python enum, when and where to use?](https://stackoverflow.com/questions/22586895/python-enum-when-and-where-to-use)
69+
- [PEP435: Adding an Enum Type to the Python Standard Library](https://www.python.org/dev/peps/pep-0435/)
70+
- [Using Enums and Django model Choices - Ben Cleary](https://medium.com/@bencleary/using-enums-as-django-model-choices-96c4cbb78b2e)

0 commit comments

Comments
 (0)