11.4. For Patterns
range(start, stop, step)
start
is inclusive, default:0
stop
is exclusive, requiredstep
default:1
11.4.1. Range
range(stop)
range(start, stop)
range(start, stop, step)
Negative step means reverse order
Range from 0 to 5:
>>> for x in range(0, 5):
... print(x)
...
0
1
2
3
4
5-times (equivalent to range(0,5)
):
>>> for x in range(5):
... print(x)
...
0
1
2
3
4
Step (each second element from 0 to 5):
>>> for x in range(0, 5, 2):
... print(x)
...
0
2
4
Negative step (each element from 5 to 0):
>>> for x in range(5, 0, -1):
... print(x)
...
5
4
3
2
1
Negative step (each second element from 5 to 0):
>>> for x in range(5, 0, -2):
... print(x)
...
5
3
1
11.4.2. Range of Length
In most cases it's a bad practice
This is a pattern taken from other languages and applied to Python
In Python we use
for
loop for doing thatThat's because Python
for
loop is aforeach
loopAlso
for x in range(len(...))
twice as slow as plainfor x in ...
>>> names = ['Mark', 'Melissa', 'Rick']
>>>
>>> for i in range(len(names)):
... name = names[i]
... print(name)
...
Mark
Melissa
Rick
But the following is more Pythonic:
>>> names = ['Mark', 'Melissa', 'Rick']
>>>
>>> for name in names:
... print(name)
...
Mark
Melissa
Rick
The output is exactly the same. The second example is more Pythonic and easier to read.
Performance:
>>> # doctest: +SKIP
... %%timeit -r1000 -n1000
... for name in DATA:
... pass
...
36.1 ns ± 7.42 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
34.1 ns ± 5.85 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
36.6 ns ± 8.1 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
36.6 ns ± 7 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
34.6 ns ± 8.2 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
>>> # doctest: +SKIP
... %%timeit -r1000 -n 1000
... for i in range(len(DATA)):
... name = DATA[i]
...
72.5 ns ± 15.2 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
71.3 ns ± 14.6 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
71 ns ± 14.8 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
71.8 ns ± 14.8 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
72.9 ns ± 16.5 ns per loop (mean ± std. dev. of 1000 runs, 1,000 loops each)
Date: 2024-12-05
Python: 3.13.0
IPython: 8.30.0
System: macOS 15.1.1
Computer: MacBook M3 Max
CPU: 16 cores (12 performance and 4 efficiency) / 3nm
RAM: 128 GB RAM LPDDR5
11.4.3. Enumerate
Later you will learn builtin
enumerate()
function which does that
>>> names = ['Mark', 'Melissa', 'Rick']
>>> i = 0
>>>
>>> for name in names:
... print(f'{i=}, {name=}')
... i += 1
...
i=0, name='Mark'
i=1, name='Melissa'
i=2, name='Rick'
11.4.4. Zip
Later you will learn builtin
zip()
function which does that
>>> firstnames = ['Mark', 'Melissa', 'Rick']
>>> lastnames = ['Watney', 'Lewis', 'Martinez']
>>>
>>> times = min(len(firstnames), len(lastnames)) # 3
>>>
>>> for i in range(times): # for i in range(3)
... fname = firstnames[i]
... lname = lastnames[i]
... print(f'{fname=}, {lname=}')
...
fname='Mark', lname='Watney'
fname='Melissa', lname='Lewis'
fname='Rick', lname='Martinez'
Because:
>>> firstnames = ['Mark', 'Melissa', 'Rick']
>>> lastnames = ['Watney', 'Lewis', 'Martinez']
>>>
>>>
>>> fname = firstnames[0]
>>> lname = lastnames[0]
>>> print(f'{fname=}, {lname=}')
fname='Mark', lname='Watney'
>>>
>>> fname = firstnames[1]
>>> lname = lastnames[1]
>>> print(f'{fname=}, {lname=}')
fname='Melissa', lname='Lewis'
>>>
>>> fname = firstnames[2]
>>> lname = lastnames[2]
>>> print(f'{fname=}, {lname=}')
fname='Rick', lname='Martinez'
11.4.5. 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: For Patterns Range
# - Difficulty: easy
# - Lines: 3
# - Minutes: 3
# %% English
# 1. Define `result: list[int]` with numbers from 0 (inclusive) to 5 (exclusive)
# 2. Use for-range pattern
# 3. Run doctests - all must succeed
# %% Polish
# 1. Zdefiniuj `result: list[int]` z liczbami od 0 (włącznie) do 5 (rozłącznie)
# 2. Użyj wzorca for-range
# 3. Uruchom doctesty - wszystkie muszą się powieść
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> assert result is not Ellipsis, \
'Assign your result to variable `result`'
>>> assert type(result) is list, \
'Variable `result` has invalid type, should be list'
>>> assert all(type(x) is int for x in result), \
'All elements in `result` should be int'
>>> from pprint import pprint
>>> pprint(result, width=79, sort_dicts=False)
[0, 1, 2, 3, 4]
"""
# Define `result: list[int]` with numbers from 0 (inclusive) to 5 (exclusive)
# Use for-range pattern
# type: list[int]
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: For Patterns Enumerate
# - Difficulty: easy
# - Lines: 6
# - Minutes: 5
# %% English
# 1. Define `result: list[tuple]`:
# - first element - month number (from 1 to 12)
# - second element - month name (January, February, March, ...)
# 2. Do not use `enumerate()` builtin function
# 3. Run doctests - all must succeed
# %% Polish
# 1. Zdefiniuj `result: list[tuple]`:
# - pierwszy element - numer miesiąca (od 1 do 12)
# - drugi element - nazwa miesiąca (January, February, March, ...)
# 2. Nie używaj wbudowanej funkcji `enumerate()`
# 3. Uruchom doctesty - wszystkie muszą się powieść
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> assert result is not Ellipsis, \
'Assign your result to variable `result`'
>>> assert type(result) is list, \
'Variable `result` has invalid type, should be list'
>>> assert all(type(x) is tuple for x in result), \
'All elements in `result` must be a tuple'
>>> assert len(result) == 12, \
'Variable `result` must contains exactly 12 elements'
>>> assert all(i>0 for i,month in result), \
'Month number must be greater than 0'
>>> assert all(i<13 for i,month in result), \
'Month number must be less than 13'
>>> from pprint import pprint
>>> pprint(result, width=79, 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',
]
# Define `result: list[tuple]`:
# - first element - month number (from 1 to 12)
# - second element - month name (January, February, March, ...)
# Do not use `enumerate()` builtin function
# type: list[tuple]
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: For Patterns Zip
# - Difficulty: easy
# - Lines: 5
# - Minutes: 5
# %% English
# 1. Define `result: list[tuple]`:
# - first element - firstname
# - second element - lastname
# 2. Do not use `zip()` builtin function
# 3. Run doctests - all must succeed
# %% Polish
# 1. Zdefiniuj `result: list[tuple]`:
# - pierwszy element - imię
# - drugi element - nazwisko
# 2. Nie używaj wbudowanej funkcji `zip()`
# 3. Uruchom doctesty - wszystkie muszą się powieść
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> assert result is not Ellipsis, \
'Assign your result to variable `result`'
>>> assert type(result) is list, \
'Variable `result` has invalid type, should be list'
>>> assert all(type(x) is tuple for x in result), \
'All elements in `result` must be a tuple'
>>> from pprint import pprint
>>> pprint(result, width=30, sort_dicts=False)
[('Mark', 'Watney'),
('Melissa', 'Lewis'),
('Rick', 'Martinez')]
"""
FIRSTNAMES = ['Mark', 'Melissa', 'Rick']
LASTNAMES = ['Watney', 'Lewis', 'Martinez']
# Define `result: list[tuple]`:
# - first element - firstname
# - second element - lastname
# Do not use `zip()` builtin function
# type: list[tuple]
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: For Patterns Zip
# - Difficulty: easy
# - Lines: 6
# - Minutes: 5
# %% English
# 1. Convert `HEADER` and `ROW` to `dict`
# 2. Define `result: dict`:
# - key - name from the header
# - value - measurement or species
# 3. Do not use `zip()` builtin function
# 4. Run doctests - all must succeed
# %% Polish
# 1. Przekonwertuj `HEADER` i `ROW` do `dict`
# 2. Zdefiniuj `result: dict`:
# - klucz - nazwa z nagłówka
# - wartość - wyniki pomiarów lub gatunek
# 3. Nie używaj wbudowanej funkcji `zip()`
# 4. Uruchom doctesty - wszystkie muszą się powieść
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> assert result is not Ellipsis, \
'Assign your result to variable `result`'
>>> assert type(result) is dict, \
'Variable `result` has invalid type, should be dict'
>>> from pprint import pprint
>>> pprint(result, width=30, sort_dicts=False)
{'firstname': 'Mark',
'lastname': 'Watney',
'age': 41}
"""
HEADER = ('firstname', 'lastname', 'age')
ROW = ('Mark', 'Watney', 41)
# Define variable `result` with converted DATA
# type: dict
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: For Patterns Iterable Zip
# - Difficulty: medium
# - Lines: 11
# - Minutes: 8
# %% English
# 1. Convert `list[tuple]` to `list[dict]`
# 2. Define `result: list[dict]`:
# - key - name from the header
# - value - measurement or species
# 3. Do not use `zip()` builtin function
# 4. Run doctests - all must succeed
# %% Polish
# 1. Przekonwertuj `list[tuple]` do `list[dict]`
# 2. Zdefiniuj `result: list[dict]`:
# - klucz - nazwa z nagłówka
# - wartość - wyniki pomiarów lub gatunek
# 3. Nie używaj wbudowanej funkcji `zip()`
# 4. Uruchom doctesty - wszystkie muszą się powieść
# %% Tests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> assert result is not Ellipsis, \
'Assign your result to variable `result`'
>>> assert type(result) is list, \
'Variable `result` has invalid type, should be list'
>>> assert all(type(x) is dict for x in result)
>>> from pprint import pprint
>>> pprint(result, width=120, sort_dicts=False)
[{'firstname': 'Mark', 'lastname': 'Watney', 'age': 41},
{'firstname': 'Melissa', 'lastname': 'Lewis', 'age': 40},
{'firstname': 'Rick', 'lastname': 'Martinez', 'age': 39},
{'firstname': 'Alex', 'lastname': 'Vogel', 'age': 40},
{'firstname': 'Chris', 'lastname': 'Beck', 'age': 36},
{'firstname': 'Beth', 'lastname': 'Johanssen', 'age': 29}]
"""
DATA = [
('firstname', 'lastname', 'age'),
('Mark', 'Watney', 41),
('Melissa', 'Lewis', 40),
('Rick', 'Martinez', 39),
('Alex', 'Vogel', 40),
('Chris', 'Beck', 36),
('Beth', 'Johanssen', 29),
]
# Define variable `result` with converted DATA
# type: list[dict]
result = ...