4.6. Idiom Enumerate¶
Enumerate sequences
Built-in generator like (lazy evaluated)
enumerate(*iterables)
required
*iterables
- 1 or many sequences or iterator objectReturn an enumerate object
The enumerate object yields pairs containing a count (from start, which defaults to zero) and a value yielded by the iterable argument.
>>> from inspect import isgeneratorfunction, isgenerator
>>>
>>>
>>> isgeneratorfunction(enumerate)
False
>>> result = enumerate(['a', 'b', 'c'])
>>> isgenerator(result)
False
4.6.1. Problem¶
>>> months = ['January', 'February', 'March']
>>> result = []
>>>
>>> i = 0
>>>
>>> for month in months:
... result.append((i, month))
... i += 1
>>>
>>> result
[(0, 'January'), (1, 'February'), (2, 'March')]
4.6.2. Solution¶
>>> months = ['January', 'February', 'March']
>>> result = enumerate(months)
>>>
>>> list(result)
[(0, 'January'), (1, 'February'), (2, 'March')]
4.6.3. Lazy Evaluation¶
>>> months = ['January', 'February', 'March']
>>> result = enumerate(months)
>>>
>>> next(result)
(0, 'January')
>>> next(result)
(1, 'February')
>>> next(result)
(2, 'March')
>>> next(result)
Traceback (most recent call last):
StopIteration
4.6.4. Dict Conversion¶
>>> months = ['January', 'February', 'March']
>>> result = enumerate(months)
>>>
>>> dict(result)
{0: 'January', 1: 'February', 2: 'March'}
>>> months = ['January', 'February', 'March']
>>> result = enumerate(months, start=1)
>>>
>>> dict(result)
{1: 'January', 2: 'February', 3: 'March'}
>>> months = ['January', 'February', 'March']
>>> result = {f'{i:02}':month for i,month in enumerate(months, start=1)}
>>>
>>> print(result)
{'01': 'January', '02': 'February', '03': 'March'}
4.6.5. Using in a Loop¶
>>> months = ['January', 'February', 'March']
>>>
>>> for i, month in enumerate(months, start=1):
... print(f'{i} -> {month}')
1 -> January
2 -> February
3 -> March
4.6.6. Assignments¶
"""
* Assignment: Idiom Enumerate Dict
* Required: yes
* Complexity: easy
* Lines of code: 1 lines
* Time: 2 min
English:
1. Define `result: dict`
2. Assign to `result` converted `DATA` to `dict`
3. Use `enumerate()`
4. Run doctests - all must succeed
Polish:
1. Zdefiniu `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 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'
>>> result
{0: 'setosa', 1: 'versicolor', 2: 'virginica'}
"""
DATA = ['setosa', 'versicolor', 'virginica']
# Dict with enumerated DATA
# type: dict[int,str]
result = ...
"""
* Assignment: Idiom Enumerate Start
* Required: yes
* Complexity: easy
* Lines of code: 1 lines
* Time: 3 min
English:
1. Convert `MONTH` into dict:
a. Keys: month number
b. Values: month name
2. Use dict() and enumerate()
3. Run doctests - all must succeed
Polish:
1. Przekonwertuj `MONTH` w słownik:
a. klucz: numer miesiąca
b. wartość: nazwa miesiąca
2. Użyj dict() i enumerate()
3. Uruchom doctesty - wszystkie muszą się powieść
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> 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())
>>> result # doctest: +NORMALIZE_WHITESPACE
{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 = ...
"""
* Assignment: Idiom Enumerate ZeroPadded
* Required: yes
* Complexity: easy
* Lines of code: 1 lines
* Time: 3 min
English:
1. Use dict comprehension and enumerate
2. Convert `MONTH` into `result: dict[str,str]`:
a. Keys: month number
b. Values: month name
3. Month number must be two letter string
(zero padded) - `f'{number:02}'`
4. Run doctests - all must succeed
Polish:
1. Użyj rozwinięcia słownikowego i enumeracji
2. Przekonwertuj `MONTH` w `result: dict[str,str]`:
a. klucz: numer miesiąca
b. wartość: nazwa miesiąca
3. Numer miesiąca ma być dwuznakowym stringiem
(wypełnij zerem) - `f'{number:02}'`
4. Uruchom doctesty - wszystkie muszą się powieść
Hints:
* `enumerate()`
* `f'{number:02}'`
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> 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())
>>> result # doctest: +NORMALIZE_WHITESPACE
{'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 = ...
"""
* Assignment: Idiom Zip LabelEncoder
* Complexity: medium
* Lines of code: 3 lines
* Time: 5 min
English:
1. From `DATA` separate header (first line) from other lines
2. Split header by comma `,` into:
a. `nrows` - number of rows
b. `nfeatures` - number of features
c. `class_labels` - species names
3. Generate `result: dict[int,str]` from `class_labels`:
a. 0: setosa
b. 1: virginica
c. 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:
a. `nrows` - liczba wierszy
b. `nfeatures` - liczba cech
c. `class_labels` - nazwy gatunków
3. Wygeneruj `result: dict[int,str]` z `class_labels`:
a. 0: setosa
b. 1: virginica
c. 2: versicolor
4. Użyj `enumerate()`
5. Uruchom doctesty - wszystkie muszą się powieść
Hints:
* `dict(enumerate())`
* `str.splitlines()`
* `str.split()`
* `str.strip()`
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> 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'
>>> result # doctest: +NORMALIZE_WHITESPACE
{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 file (note the list[tuple] format!)
# type: dict[int,str]
result = ...
"""
* Assignment: Idioms Enumerate Impl
* Complexity: medium
* Lines of code: 7 lines
* Time: 13 min
English:
1. Write own implementation of a built-in `enumerate()` function
2. Define function `myenumerate` with parameters:
a. parameter `iterable: list | tuple`
b. parameter `start: int`
3. Don't validate arguments and assume, that user will:
a. always pass valid type of arguments
b. iterable length will always be greater than 0
4. Run doctests - all must succeed
Polish:
1. Zaimplementuj własne rozwiązanie wbudowanej funkcji `enumerate()`
2. Zdefiniuj funkcję `myenumerate` z parametrami:
a. parametr `iterable: list | tuple`
b. parametr `start: int`
3. Nie waliduj argumentów i przyjmij, że użytkownik:
a. zawsze poda argumenty poprawnych typów
b. długość iterable będzie większa od 0
4. Uruchom doctesty - wszystkie muszą się powieść
Hint:
* https://github.com/python/cpython/blob/main/Objects/enumobject.c
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> 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):
...