Hello everyone,
I’d like to propose an update to the Python sublist
exercise to use the standard enum.Enum
class for its constants. The current template is functional but I believe we can make it more robust, readable, and educational by adopting this modern Python feature.
Current Approach
The current sublist.py
stub guides the user to define module-level constants, like so:
# sublist.py (current stub)
SUBLIST = None
SUPERLIST = None
EQUAL = None
UNEQUAL = None
def sublist(list_one, list_two):
pass
The accompanying sublist_test.py
then imports these constants directly:
# sublist_test.py (current)
from sublist import (
sublist,
SUBLIST,
SUPERLIST,
EQUAL,
UNEQUAL,
)
class SublistTest(unittest.TestCase):
def test_empty_lists(self):
self.assertEqual(sublist([], []), EQUAL)
# ... etc
While this works, it misses an opportunity to teach a more modern and safer approach. The stub file itself even links to the Wikipedia page for enumerated types, which makes Enum
a natural fit.
Reasons for the Change
Moving to Enum
offers several key advantages:
- Type Safety and Clarity : An
Enum
creates a distinct, new type. This makes the function signature forsublist
far more descriptive and prevents accidental cross-comparison bugs.def sublist(...) -> ListRelation:
is much clearer thandef sublist(...) -> int:
. - Namespacing and Readability : It groups the related constants (
SUBLIST
,SUPERLIST
, etc.) under a single, logical namespace (ListRelation
). This improves organization and makes the code easier to read. - Bug Prevention : Using module-level variables can lead to subtle bugs. For example, a typo like
UNEQAUL = 4
would create a new variable, and a test might pass or fail silently. With an Enum,ListRelation.UNEQAUL
would immediately raise anAttributeError
, making the error obvious and easy to fix. - Teaching Modern Python :
Enum
has been a standard part of Python since version 3.4. Introducing it in an exercise like this is a great way to expose learners to powerful, idiomatic features of the language.
Proposed New Template
I suggest we update the sublist.py
stub to the following:
# sublist.py (proposed new stub)
from enum import Enum
class ListRelation(Enum):
"""
An enumeration to represent the relationship between two lists.
"""
EQUAL = 1
SUBLIST = 2
SUPERLIST = 3
UNEQUAL = 4
def sublist(list_one: list, list_two: list) -> ListRelation:
"""
Determines if list_one is a sublist, superlist, or equal to list_two.
"""
pass
This is cleaner and provides a much better starting point for the student.
Ensuring Backwards Compatibility
A major concern with changing a popular exercise is breaking the thousands of already-published community solutions. We can address this with a small, non-intrusive change to the test file.
By modifying sublist_test.py
, we can make it compatible with both the old (module-level constants) and new (Enum
) approaches. The key is to try importing the Enum
first and falling back to the old constants if it fails.
Here is a proposed change for the top of sublist_test.py
:
# sublist_test.py (proposed new test setup)
import unittest
from sublist import sublist
# Try to import the modern Enum-based constants first.
# Fall back to the old module-level constants for backwards compatibility.
try:
from sublist import ListRelation
SUBLIST = ListRelation.SUBLIST
SUPERLIST = ListRelation.SUPERLIST
EQUAL = ListRelation.EQUAL
UNEQUAL = ListRelation.UNEQUAL
except ImportError:
from sublist import SUBLIST, SUPERLIST, EQUAL, UNEQUAL
class SublistTest(unittest.TestCase):
# ... all test cases remain unchanged
def test_empty_lists(self):
self.assertEqual(sublist([], []), EQUAL)
This approach is fully backwards-compatible. Old solutions will cause the ImportError
, and the test file will fall back to importing the constants as it does now. New solutions based on the Enum
template will work seamlessly. No existing solutions will be broken.
This change would allow us to improve the exercise for future students while respecting the work of past contributors.
I look forward to hearing your thoughts on this proposal.
Best, Jegors