6.4. Iterable Recap
Recap information about
tuple
,list
andset
tuple
- fast and memory efficientlist
- extensible and flexibleset
- unique elements, fast lookup
Why are there separate tuple and list data types? [2]
Lists and tuples, while similar in many respects, are generally used in fundamentally different ways. Tuples can be thought of as being similar to Pascal records or C structs; they're small collections of related data which may be of different types which are operated on as a group. For example, a Cartesian coordinate is appropriately represented as a tuple of two or three numbers.
Lists, on the other hand, are more like arrays in other languages. They
tend to hold a varying number of objects all of which have the same type
and which are operated on one-by-one. For example, os.listdir('.')
returns a list of strings representing the files in the current directory.
Functions which operate on this output would generally not break if you
added another file or two to the directory.
Tuples are immutable, meaning that once a tuple has been created, you can't replace any of its elements with a new value. Lists are mutable, meaning that you can always change a list's elements. Only immutable elements can be used as dictionary keys, and hence only tuples and not lists can be used as keys.
>>> data = [1, 2, 3]
>>> id(data)
4441671808
>>>
>>> data += [4, 5, 6]
>>> id(data)
4441671808
>>>
>>> data
[1, 2, 3, 4, 5, 6]
>>> data = (1, 2, 3)
>>> id(data)
4437523008
>>>
>>> data += (4, 5, 6)
>>> id(data)
4450573696
>>>
>>> data
(1, 2, 3, 4, 5, 6)
6.4.1. Tuple
Immutable - cannot add, modify or remove items
Stores elements of any type
Keeps order of inserting elements
Possible to getitem and slice
Elements can duplicate
One contingent block of data in memory
Whole tuple must be defined at once

Figure 6.1. Memory representation for tuple
6.4.2. List
Mutable - can add, remove, and modify items
Stores elements of any type
Keeps order of inserting elements
Possible to getitem and slice
Elements can duplicate
Implemented in memory as list of references to objects
Objects are scattered in memory

Figure 6.2. Memory representation for list
6.4.3. Set
Mutable - can add, remove, and modify items
Stores only hashable elements (int, float, bool, None, str, tuple)
Does not keep order of inserting elements
It is not possible to getitem and slice
Elements cannot duplicate
Set is unordered data structure and do not record element position or insertion
6.4.4. Memory Footprint
Python 3.12
Python 3.13
>>> from sys import getsizeof
>>>
>>>
>>> getsizeof( (1,2,3) )
64
>>>
>>> getsizeof( [1,2,3] )
88
>>>
>>> getsizeof( {1,2,3} )
216
6.4.5. Memory

Figure 6.3. Memory representation for list
and tuple
6.4.6. Performance
Date: 2024-10-22
Python: 3.13.0
IPython: 8.28.0
System: macOS 15.0.1
Computer: MacBook M3 Max
CPU: 16 cores (12 performance and 4 efficiency) / 3nm
RAM: 128 GB RAM LPDDR5
O(n)
- lookup (contains) in list and tupleO(1)
- lookup (contains) in set
Short sequence of elements:
>>> %%timeit -r 10_000 -n 10_000 # doctest: +SKIP
... 0 in (1, 2, 3)
...
15.9 ns ± 1.51 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
15.8 ns ± 1.5 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
15.8 ns ± 1.35 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
>>> %%timeit -r 10_000 -n 10_000 # doctest: +SKIP
... 0 in [1, 2, 3]
...
15.9 ns ± 1.55 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
15.7 ns ± 0.957 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
15.8 ns ± 1.31 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
>>> %%timeit -r 10_000 -n 10_000 # doctest: +SKIP
... 0 in {1, 2, 3}
...
8.06 ns ± 1.07 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
8.03 ns ± 0.967 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
8.08 ns ± 0.997 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
Long sequence of elements:
>>> %%timeit -r 10_000 -n 10_000 # doctest: +SKIP
... 0 in (1, 2, 3, 4, 5, 6, 7, 8, 9)
...
35.3 ns ± 2.27 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
35.3 ns ± 2.3 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
35.3 ns ± 2.15 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
>>> %%timeit -r 10_000 -n 10_000 # doctest: +SKIP
... 0 in [1, 2, 3, 4, 5, 6, 7, 8, 9]
...
35.3 ns ± 2.32 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
35.3 ns ± 2.27 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
35.3 ns ± 2.05 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
>>> %%timeit -r 10_000 -n 10_000 # doctest: +SKIP
... 0 in {1, 2, 3, 4, 5, 6, 7, 8, 9}
...
8.05 ns ± 1.01 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
7.99 ns ± 0.973 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
7.99 ns ± 0.903 ns per loop (mean ± std. dev. of 10000 runs, 10,000 loops each)
6.4.7. References
6.4.8. Assignments
# %% About
# - Name: Iterable Recap Select
# - Difficulty: easy
# - Lines: 1
# - Minutes: 3
# %% 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
# %% English
# 1. Define `result: tuple` representing all species
# 2. To convert table use multiline select with `alt` or `alt+shift`
# key in your IDE
# 3. Do not use `slice`, `getitem`, `for`, `while` or any other
# control-flow statement
# 4. Run doctests - all must succeed
# %% Polish
# 1. Zdefiniuj `result: tuple` z nazwami gatunków
# 2. Do konwersji tabelki wykorzystaj zaznaczanie wielu linijek za pomocą
# klawisza `alt` lub `alt+shift` w Twoim IDE
# 3. Nie używaj `slice`, `getitem`, `for`, `while` lub jakiejkolwiek innej
# instrukcji sterującej
# 4. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `ALT` + `left mouse button` = multiple select
# - `ALT` + `SHIFT` + `left mouse button drag` = vertical selection
# %% Doctests
"""
>>> 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 tuple, \
'Variable `result` has invalid type, should be tuple'
>>> assert all(type(x) is str for x in result), \
'All elements in result should be str'
>>> assert len(result) == 5, \
'Variable `result` length should be 5'
>>> assert result.count('virginica') == 2, \
'Result should have 2 elements of virginica'
>>> assert result.count('setosa') == 1, \
'Result should have 1 element of setosa'
>>> assert result.count('versicolor') == 2, \
'Result should have 2 elements of versicolor'
>>> assert ('sepal_length' not in result
... and 'sepal_width' not in result
... and 'petal_length' not in result
... and 'petal_width' not in result
... and 'species' not in result)
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% Imports
# %% Types
result: tuple[str,str,str,str,str]
# %% Data
DATA = """
sepal_length,sepal_width,petal_length,petal_width,species
5.8,2.7,5.1,1.9,virginica
5.1,3.5,1.4,0.2,setosa
5.7,2.8,4.1,1.3,versicolor
6.3,2.9,5.6,1.8,virginica
6.4,3.2,4.5,1.5,versicolor
"""
# %% Result
result = ...
# %% About
# - Name: Iterable Recap Mean
# - Difficulty: medium
# - Lines: 8
# - Minutes: 8
# %% 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
# %% English
# 1. Define variables:
# - `result_a` with arithmetic mean of column `sepal_length`
# - `result_b` with arithmetic mean of column `sepal_width`
# - `result_c` with arithmetic mean of column `petal_length`
# - `result_d` with arithmetic mean of column `petal_width`
# 2. Use column selection with `alt` key shortcut
# 3. Do not use `str.split()`, `slice`, `getitem`, `for`, `while`
# or any other control-flow statement
# 4. Non-functional requirements:
# - practice tuple creation syntax, not automation
# - practice vertical selection in IDE
# 5. Run doctests - all must succeed
# %% Polish
# 1. Zdefiniuj zmienne:
# - `result_a` z średnią arytmetyczną kolumny `sepal_length`
# - `result_b` z średnią arytmetyczną kolumny `sepal_width`
# - `result_c` z średnią arytmetyczną kolumny `petal_length`
# - `result_d` z średnią arytmetyczną kolumny `petal_width`
# 2. Wykorzystaj zaznaczanie kolumnowe za pomocą klawisza `alt`
# 3. Nie używaj `str.split()`, `slice`, `getitem`, `for`, `while`
# lub jakiejkolwiek innej instrukcji sterującej
# 4. Wymagania niefunkcjonalne:
# - przećwicz składnię tworzenia `tuple`, a nie automatyzację,
# - przećwicz zaznaczanie pionowe w IDE
# 5. Uruchom doctesty - wszystkie muszą się powieść
# %% Hints
# - `mean = sum(...) / len(...)`
# - `ALT` + `left mouse button` = multiple select
# - `ALT` + `SHIFT` + `left mouse button drag` = vertical selection
# - `ALT` + `SHIFT` + `right` = select word to the right (macOS)
# - `ALT` + `SHIFT` + `left` = select word to the left (macOS)
# - `CTRL` + `SHIFT` + `right` = select word to the right (Windows)
# - `CTRL` + `SHIFT` + `left` = select word to the left (Windows)
# - `CTRL` + `right` = jump over the word to the right
# - `CTRL` + `left` = jump over the word to the left
# - `CTRL` + `ALT` + L = Reformat Code on Windows
# - `CMD` + `ALT` + L = Reformat Code on macOS
# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'
>>> assert result_a is not Ellipsis, \
'Assign your result to variable `result_a`'
>>> assert result_b is not Ellipsis, \
'Assign your result to variable `result_b`'
>>> assert result_c is not Ellipsis, \
'Assign your result to variable `result_c`'
>>> assert result_d is not Ellipsis, \
'Assign your result to variable `result_d`'
>>> assert type(result_a) is float, \
'Variable `result_a` has invalid type, should be float'
>>> assert type(result_b) is float, \
'Variable `result_b` has invalid type, should be float'
>>> assert type(result_c) is float, \
'Variable `result_c` has invalid type, should be float'
>>> assert type(result_d) is float, \
'Variable `result_d` has invalid type, should be float'
>>> result_a
5.86
>>> result_b
3.02
>>> result_c
4.14
>>> result_d
1.34
"""
# %% Run
# - PyCharm: right-click in the editor and `Run Doctest in ...`
# - PyCharm: keyboard shortcut `Control + Shift + F10`
# - Terminal: `python -m doctest -v myfile.py`
# %% Imports
# %% Types
result_a: float
result_b: float
result_c: float
result_d: float
# %% Data
DATA = """
sepal_length,sepal_width,petal_length,petal_width,species
5.8,2.7,5.1,1.9,virginica
5.1,3.5,1.4,0.2,setosa
5.7,2.8,4.1,1.3,versicolor
6.3,2.9,5.6,1.8,virginica
6.4,3.2,4.5,1.5,versicolor
"""
# %% Result
result_a = ...
result_b = ...
result_c = ...
result_d = ...