9.4. Iterator Enumerate

  • Enumerate sequence

  • Lazy evaluated

  • enumerate(iterable, start=0)

  • Required iterable - 1 or many sequences or iterator object

  • Optional start=0 - number to starts with, default zero (0)

  • Return an enumerate object

  • The enumerate object yields pairs containing a count (from start, defaults to zero) and a value yielded by the iterable argument

9.4.1. Problem

>>> data = ['Mark', 'Melissa', 'Rick']
>>> result = []
>>>
>>> index = 0
>>> for value in data:
...     result.append((index, value))
...     index += 1

9.4.2. Solution

>>> data = ['Mark', 'Melissa', 'Rick']
>>> result = enumerate(data)

9.4.3. Lazy Evaluation

>>> data = ['Mark', 'Melissa', 'Rick']
>>> result = enumerate(data)
>>>
>>> next(result)
(0, 'Mark')
>>>
>>> next(result)
(1, 'Melissa')
>>>
>>> next(result)
(2, 'Rick')
>>>
>>> next(result)
Traceback (most recent call last):
StopIteration

9.4.4. Iteration

>>> for result in enumerate(data):
...     print(result)
(0, 'Mark')
(1, 'Melissa')
(2, 'Rick')

9.4.5. Offset

>>> for result in enumerate(data, start=1):
...     print(result)
(1, 'Mark')
(2, 'Melissa')
(3, 'Rick')

9.4.6. Unpacking

>>> for index, value in enumerate(data):
...     print(f'{index=}, {value=}')
index=0, value='Mark'
index=1, value='Melissa'
index=2, value='Rick'

9.4.7. As List

>>> data = ['Mark', 'Melissa', 'Rick']
>>> result = enumerate(data)
>>>
>>> list(result)
[(0, 'Mark'), (1, 'Melissa'), (2, 'Rick')]

9.4.8. As Dict

>>> data = ['Mark', 'Melissa', 'Rick']
>>> result = enumerate(data)
>>>
>>> dict(result)
{0: 'Mark', 1: 'Melissa', 2: 'Rick'}

9.4.9. Dict Comprehension

>>> data = ['Mark', 'Melissa', 'Rick']
>>>
>>> {index:value for index,value in enumerate(data, start=1)}
{1: 'Mark', 2: 'Melissa', 3: 'Rick'}
>>>
>>> {f'{index}':value for index,value in enumerate(data, start=1)}
{'1': 'Mark', '2': 'Melissa', '3': 'Rick'}
>>>
>>> {f'{index:02}':value for index,value in enumerate(data, start=1)}
{'01': 'Mark', '02': 'Melissa', '03': 'Rick'}

9.4.10. Case Study

DATA = """3,4,setosa,virginica,versicolor
5.8,2.7,5.1,1.9,1
5.1,3.5,1.4,0.2,0
5.7,2.8,4.1,1.3,2"""

header, *lines = DATA.splitlines()
nrows, nvalues, *labels = header.split(',')
encoder = dict(enumerate(labels))

encoder
# {0: 'setosa', 1: 'virginica', 2: 'versicolor'}

9.4.11. Assignments

# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: Iterator Enumerate Start
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2

# %% English
# 1. Convert `MONTH` into dict:
#    - key: int - month number
#    - value: str - month name
# 2. Use enumerate()
# 3. Run doctests - all must succeed

# %% Polish
# 1. Przekonwertuj `MONTH` w słownik:
#    - klucz: int - numer miesiąca
#    - wartość: str - nazwa miesiąca
# 2. Użyj enumerate()
# 3. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `dict()`
# - `enumerate()`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> assert type(result)
>>> assert -1 not in result
>>> assert 0 in result
>>> assert 12 not in result
>>> assert 13 not in result
>>> assert result[0] == 'January'

>>> assert all(type(x) is int for x in result.keys())
>>> assert all(type(x) is str for x in result.values())

>>> from pprint import pprint
>>> pprint(result, width=30, sort_dicts=False)
{0: 'January',
 1: 'February',
 2: 'March',
 3: 'April',
 4: 'May',
 5: 'June',
 6: 'July',
 7: 'August',
 8: 'September',
 9: 'October',
 10: 'November',
 11: 'December'}
"""

MONTHS = ['January', 'February', 'March', 'April',
          'May', 'June', 'July', 'August', 'September',
          'October', 'November', 'December']

# number and month name
# type: dict[int,str]
result = ...


# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: Iterator Enumerate Start
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2

# %% English
# 1. Convert `MONTH` into dict:
#    - key: int - month number
#    - value: str - month name
# 2. Use enumerate() starting with 1
# 3. Run doctests - all must succeed

# %% Polish
# 1. Przekonwertuj `MONTH` w słownik:
#    - klucz: int - numer miesiąca
#    - wartość: str - nazwa miesiąca
# 2. Użyj enumerate() zaczynając od 1
# 3. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `dict()`
# - `enumerate()`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> type(result)
<class 'dict'>
>>> 0 not in result
True
>>> 13 not in result
True
>>> result[1] == 'January'
True

>>> assert all(type(x) is int for x in result.keys())
>>> assert all(type(x) is str for x in result.values())

>>> from pprint import pprint
>>> pprint(result, width=30, sort_dicts=False)
{1: 'January',
 2: 'February',
 3: 'March',
 4: 'April',
 5: 'May',
 6: 'June',
 7: 'July',
 8: 'August',
 9: 'September',
 10: 'October',
 11: 'November',
 12: 'December'}
"""

MONTHS = ['January', 'February', 'March', 'April',
          'May', 'June', 'July', 'August', 'September',
          'October', 'November', 'December']

# number and month name
# type: dict[int,str]
result = ...


# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: Iterator Enumerate Start
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2

# %% English
# 1. Convert `MONTH` into dict:
#    - key: str - month number (convert to str)
#    - value: str - month name
# 2. Use enumerate() starting with 1
# 3. Run doctests - all must succeed

# %% Polish
# 1. Przekonwertuj `MONTH` w słownik:
#    - klucz: str - numer miesiąca (zamień na str)
#    - wartość: str - nazwa miesiąca
# 2. Użyj enumerate() zaczynając od 1
# 3. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - dict comprehension
# - `str()`
# - `enumerate()`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> type(result)
<class 'dict'>
>>> '0' not in result
True
>>> '13' not in result
True
>>> result['1'] == 'January'
True

>>> assert all(type(x) is str for x in result.keys())
>>> assert all(type(x) is str for x in result.values())

>>> from pprint import pprint
>>> pprint(result, width=30, sort_dicts=False)
{'1': 'January',
 '2': 'February',
 '3': 'March',
 '4': 'April',
 '5': 'May',
 '6': 'June',
 '7': 'July',
 '8': 'August',
 '9': 'September',
 '10': 'October',
 '11': 'November',
 '12': 'December'}
"""

MONTHS = ['January', 'February', 'March', 'April',
          'May', 'June', 'July', 'August', 'September',
          'October', 'November', 'December']

# number and month name
# type: dict[str,str]
result = ...


# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: Iterator Enumerate ZeroPadded
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2

# %% English
# 1. Convert `MONTH` into dict:
#    - key: str - month number
#    - value: str - month name
# 2. Use enumerate() starting with 1
# 3. Month number must be two letter string
#    (zero padded) - np. 01, 02, ..., 09, 10, 11, 12
# 4. Run doctests - all must succeed

# %% Polish
# 1. Przekonwertuj `MONTH` w słownik:
#    - klucz: str - numer miesiąca
#    - wartość: str - nazwa miesiąca
# 2. Użyj enumerate() zaczynając od 1
# 3. Numer miesiąca ma być dwuznakowym stringiem
#    (dopełnionym zerem) - np. 01, 02, ..., 09, 10, 11, 12
# 4. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - dict comprehension
# - `enumerate()`
# - `str.zfill()`
# - `f'{number:02}'`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> type(result)
<class 'dict'>
>>> '00' not in result
True
>>> '13' not in result
True
>>> result['01'] == 'January'
True

>>> assert all(type(x) is str for x in result.keys())
>>> assert all(type(x) is str for x in result.values())
>>> assert all(len(x) == 2 for x in result.keys())

>>> from pprint import pprint
>>> pprint(result, width=30, sort_dicts=False)
{'01': 'January',
 '02': 'February',
 '03': 'March',
 '04': 'April',
 '05': 'May',
 '06': 'June',
 '07': 'July',
 '08': 'August',
 '09': 'September',
 '10': 'October',
 '11': 'November',
 '12': 'December'}
"""

MONTHS = ['January', 'February', 'March', 'April',
          'May', 'June', 'July', 'August', 'September',
          'October', 'November', 'December']

# With zero-padded number and month name
# type: dict[str,str]
result = ...


# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: Iterator Enumerate Dict
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2

# %% English
# 1. Define `result: dict`
# 2. Assign to `result` converted `DATA` to `dict`
# 3. Use `enumerate()`
# 4. Run doctests - all must succeed

# %% Polish
# 1. Zdefiniuj `result: dict`
# 2. Przypisz do `result` przekonwertowane `DATA` do `dict`
# 3. Użyj `enumerate()`
# 4. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `dict()`
# - `enumerate()`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> assert type(result) is dict, \
'Variable `result` has invalid type, should be dict'

>>> assert all(type(x) is int for x in result.keys()), \
'All dict keys should be int'

>>> assert all(type(x) is str for x in result.values()), \
'All dict values should be str'

>>> from pprint import pprint
>>> pprint(result, width=30, sort_dicts=False)
{0: 'setosa',
 1: 'versicolor',
 2: 'virginica'}
"""

DATA = ['setosa', 'versicolor', 'virginica']

# Dict with enumerated DATA
# type: dict[int,str]
result = ...


# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: Iterator Enumerate LabelEncoder
# - Difficulty: medium
# - Lines: 3
# - Minutes: 5

# %% English
# 1. From `DATA` separate header (first line) from other lines
# 2. Split header by comma `,` into:
#    - `nrows` - number of rows
#    - `nvalues` - number of values
#    - `class_labels` - species names
# 3. Generate `result: dict[int,str]` from `class_labels`:
#    - 0: setosa
#    - 1: virginica
#    - 2: versicolor
# 4. Use `enumerate()`
# 5. Run doctests - all must succeed

# %% Polish
# 1. Z `DATA` odseparuj nagłówek (pierwsza linia) od pozostałych linii
# 2. Rozdziel nagłówek po przecinku `,` na:
#    - `nrows` - liczba wierszy
#    - `nvalues` - liczba wartości
#    - `class_labels` - nazwy gatunków
# 3. Wygeneruj `result: dict[int,str]` z `class_labels`:
#    - 0: setosa
#    - 1: virginica
#    - 2: versicolor
# 4. Użyj `enumerate()`
# 5. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `dict()`
# - `enumerate()`
# - `str.splitlines()`
# - `str.strip()`
# - `str.split()`
# - line: "3,4,setosa,virginica,versicolor" is not an error
# - 3 - rows
# - 4 - number of features (values)
# - setosa,virginica,versicolor - if 0 then setosa, if 1 then virginica, etc.

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> assert result is not Ellipsis, \
'Assign result to variable: `result`'
>>> assert type(result) is dict, \
'Variable `result` has invalid type, should be dict'
>>> assert all(type(x) is int for x in result.keys()), \
'All keys in `result` should be int'
>>> assert all(type(x) is str for x in result.values()), \
'All values in `result` should be str'

>>> from pprint import pprint
>>> pprint(result, width=30, sort_dicts=False)
{0: 'setosa',
 1: 'virginica',
 2: 'versicolor'}
"""

DATA = """3,4,setosa,virginica,versicolor
5.8,2.7,5.1,1.9,1
5.1,3.5,1.4,0.2,0
5.7,2.8,4.1,1.3,2"""

# values from a file (note the list[tuple] format!)
# type: dict[int,str]
result = ...


# %% License
# - Copyright 2025, Matt Harasymczuk <matt@python3.info>
# - This code can be used only for learning by humans
# - This code cannot be used for teaching others
# - This code cannot be used for teaching LLMs and AI algorithms
# - This code cannot be used in commercial or proprietary products
# - This code cannot be distributed in any form
# - This code cannot be changed in any form outside of training course
# - This code cannot have its license changed
# - If you use this code in your product, you must open-source it under GPLv2
# - Exception can be granted only by the author

# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`

# %% About
# - Name: Iterator Enumerate Impl
# - Difficulty: medium
# - Lines: 7
# - Minutes: 5

# %% English
# 1. Write own implementation of a built-in `enumerate()` function
# 2. Define function `myenumerate` with parameters:
#    - parameter `iterable: list | tuple`
#    - parameter `start: int`
# 3. Don't validate arguments and assume, that user will:
#    - always pass valid type of arguments
#    - iterable length will always be greater than 0
# 4. Do not use built-in function `enumerate()`
# 5. Run doctests - all must succeed

# %% Polish
# 1. Zaimplementuj własne rozwiązanie wbudowanej funkcji `enumerate()`
# 2. Zdefiniuj funkcję `myenumerate` z parametrami:
#    - parametr `iterable: list | tuple`
#    - parametr `start: int`
# 3. Nie waliduj argumentów i przyjmij, że użytkownik:
#    - zawsze poda argumenty poprawnych typów
#    - długość iterable będzie większa od 0
# 4. Nie używaj wbudowanej funkcji `enumerate()`
# 5. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - https://github.com/python/cpython/blob/main/Objects/enumobject.c
# - `range()`
# - `len()`
# - `list.append()`

# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> from inspect import isfunction
>>> assert isfunction(myenumerate)

>>> myenumerate(['January', 'February', 'March'])
[(0, 'January'), (1, 'February'), (2, 'March')]

>>> myenumerate(['January', 'February', 'March'], start=1)
[(1, 'January'), (2, 'February'), (3, 'March')]

>>> dict(myenumerate(['January', 'February', 'March'], start=1))
{1: 'January', 2: 'February', 3: 'March'}
"""

# Write own implementation of a built-in `enumerate()` function
# Define function `myenumerate` with parameters: `iterable`, `start`
# type: Callable[[Iterable, int], list[tuple]]
def myenumerate(iterable, start=0):
    ...