diff --git a/hashtable/01_hashtable_prototype/02_insert_a_key_value_pair/hashtable.py b/hashtable/01_hashtable_prototype/02_insert_a_key_value_pair/hashtable.py index c018b7f71d..4f8fe0917f 100644 --- a/hashtable/01_hashtable_prototype/02_insert_a_key_value_pair/hashtable.py +++ b/hashtable/01_hashtable_prototype/02_insert_a_key_value_pair/hashtable.py @@ -1,6 +1,6 @@ # hashtable.py -BLANK = object() +BLANK = sentinel("BLANK") class HashTable: diff --git a/hashtable/01_hashtable_prototype/03_find_a_value_by_key/hashtable.py b/hashtable/01_hashtable_prototype/03_find_a_value_by_key/hashtable.py index 480f1c12f5..1222f4b093 100644 --- a/hashtable/01_hashtable_prototype/03_find_a_value_by_key/hashtable.py +++ b/hashtable/01_hashtable_prototype/03_find_a_value_by_key/hashtable.py @@ -1,6 +1,6 @@ # hashtable.py -BLANK = object() +BLANK = sentinel("BLANK") class HashTable: diff --git a/hashtable/01_hashtable_prototype/04_delete_a_key_value_pair/hashtable.py b/hashtable/01_hashtable_prototype/04_delete_a_key_value_pair/hashtable.py index 0b4d533bd2..44b2c6db16 100644 --- a/hashtable/01_hashtable_prototype/04_delete_a_key_value_pair/hashtable.py +++ b/hashtable/01_hashtable_prototype/04_delete_a_key_value_pair/hashtable.py @@ -1,6 +1,6 @@ # hashtable.py -BLANK = object() +BLANK = sentinel("BLANK") class HashTable: diff --git a/hashtable/01_hashtable_prototype/05_update_the_value_of_an_existing_pair/hashtable.py b/hashtable/01_hashtable_prototype/05_update_the_value_of_an_existing_pair/hashtable.py index 0b4d533bd2..44b2c6db16 100644 --- a/hashtable/01_hashtable_prototype/05_update_the_value_of_an_existing_pair/hashtable.py +++ b/hashtable/01_hashtable_prototype/05_update_the_value_of_an_existing_pair/hashtable.py @@ -1,6 +1,6 @@ # hashtable.py -BLANK = object() +BLANK = sentinel("BLANK") class HashTable: diff --git a/hashtable/01_hashtable_prototype/07_use_defensive_copying/hashtable.py b/hashtable/01_hashtable_prototype/07_use_defensive_copying/hashtable.py index 2b648b9a10..9fd10feeeb 100644 --- a/hashtable/01_hashtable_prototype/07_use_defensive_copying/hashtable.py +++ b/hashtable/01_hashtable_prototype/07_use_defensive_copying/hashtable.py @@ -1,5 +1,6 @@ # hashtable.py +import copy from typing import Any, NamedTuple @@ -46,7 +47,7 @@ def get(self, key, default=None): @property def pairs(self): - return [pair for pair in self._pairs if pair] + return copy.deepcopy([pair for pair in self._pairs if pair]) def _index(self, key): return hash(key) % len(self) diff --git a/hashtable/02_linear_probing/hashtable.py b/hashtable/02_linear_probing/hashtable.py index 17ba0e5398..cf2b918f41 100644 --- a/hashtable/02_linear_probing/hashtable.py +++ b/hashtable/02_linear_probing/hashtable.py @@ -2,7 +2,7 @@ from typing import Any, NamedTuple -DELETED = object() +DELETED = sentinel("DELETED") class Pair(NamedTuple): diff --git a/hashtable/03_autoresize/hashtable.py b/hashtable/03_autoresize/hashtable.py index 77b8963761..eba084d860 100644 --- a/hashtable/03_autoresize/hashtable.py +++ b/hashtable/03_autoresize/hashtable.py @@ -2,7 +2,7 @@ from typing import Any, NamedTuple -DELETED = object() +DELETED = sentinel("DELETED") class Pair(NamedTuple): diff --git a/hashtable/04_load_factor/hashtable.py b/hashtable/04_load_factor/hashtable.py index e440e16b5a..c8202b45c3 100644 --- a/hashtable/04_load_factor/hashtable.py +++ b/hashtable/04_load_factor/hashtable.py @@ -2,7 +2,7 @@ from typing import Any, NamedTuple -DELETED = object() +DELETED = sentinel("DELETED") class Pair(NamedTuple): diff --git a/hashtable/05_separate_chaining/hashtable.py b/hashtable/05_separate_chaining/hashtable.py index 7ff3754c94..60926b2605 100644 --- a/hashtable/05_separate_chaining/hashtable.py +++ b/hashtable/05_separate_chaining/hashtable.py @@ -91,7 +91,7 @@ def get(self, key, default=None): @property def pairs(self): - return {pair for bucket in self._buckets for pair in bucket} + return {*bucket for bucket in self._buckets} @property def values(self): diff --git a/hashtable/README.md b/hashtable/README.md index 68772e9cec..1df7aa37ba 100644 --- a/hashtable/README.md +++ b/hashtable/README.md @@ -4,10 +4,12 @@ Code supplementing the [tutorial on the hash table](https://realpython.com/pytho ## Installation +The code requires Python 3.15 or later. It uses the built-in `sentinel()` and unpacking in comprehensions, which are new in Python 3.15. + To get started, create and activate a new virtual environment, and then install the required dependencies into it: ```shell -$ python3 -m venv venv --prompt=hashtable +$ python3.15 -m venv venv --prompt=hashtable $ source venv/bin/activate (hashtable) $ python -m pip install -r requirements.txt ``` diff --git a/hashtable/requirements.txt b/hashtable/requirements.txt index 5371299fc3..43d9132597 100644 --- a/hashtable/requirements.txt +++ b/hashtable/requirements.txt @@ -1,9 +1,6 @@ -attrs==21.4.0 -iniconfig==1.1.1 -packaging==21.3 -pluggy==1.0.0 -py==1.11.0 -pyparsing==3.0.7 -pytest==7.0.1 -pytest-unordered==0.4.1 -tomli==2.0.1 +iniconfig==2.3.1 +packaging==26.3 +pluggy==1.7.0 +pygments==2.21.0 +pytest==9.1.1 +pytest-unordered==0.8.0 diff --git a/pyproject.toml b/pyproject.toml index e26dbfd9e6..e6e772c7a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ exclude = [ "python315-frozendict/", "python315-lazy-imports", "python315-new-features", + "hashtable", "ai-benchmark", "python-debugging-pdb" ]