5.2. Sequence Tuple

5.2.1. Rationale

  • Immutable - cannot add, modify or remove items

5.2.2. Definition

Defining empty tuple with () is used more often, but tuple() is more explicit:

>>> data = ()
>>> data = tuple()

Can store elements of any type:

>>> data = (1, 2, 3)
>>> data = (1.1, 2.2, 3.3)
>>> data = (True, False)
>>> data = ('a', 'b', 'c')
>>> data = ('a', 1, 2.2, True, None)

Brackets are optional, but it's a good practice to always write them:

>>> data = (1, 2, 3)
>>> data = 1, 2, 3

Single element tuple require comma at the end (important!):

>>> data = (1,)
>>> type(data)
<class 'tuple'>
>>> data = (1)
>>> type(data)
<class 'int'>

Comma after last element of multi value tuple is optional:

>>> data = (1, 2)
>>> type(data)
<class 'tuple'>
>>> data = (1, 2,)
>>> type(data)
<class 'tuple'>

5.2.3. Type Casting

Builtin function tuple() converts argument to tuple

>>> data = 'abcd'
>>> tuple(data)
('a', 'b', 'c', 'd')
>>> data = ['a', 'b', 'c', 'd']
>>> tuple(data)
('a', 'b', 'c', 'd')
>>> data = ('a', 'b', 'c', 'd')
>>> tuple(data)
('a', 'b', 'c', 'd')
>>> tuple('a', 'b', 'c', 'd')
Traceback (most recent call last):
TypeError: tuple expected at most 1 argument, got 4

5.2.4. GetItem

  • More information in Sequence GetItem

  • More information in Sequence Slice

>>> data = ('a', 'b', 'c', 'd')
>>> data[0]
'a'
>>> data[1]
'b'
>>> data[2]
'c'
>>> data[3]
'd'

5.2.5. Tuple or Int, Float, Str

>>> x = 1           # int
>>> x = 1.          # float
>>> x = 1,          # tuple
>>> x = (1)         # int
>>> x = (1.)        # float
>>> x = (1,)        # tuple
>>> x = 'one'       # str
>>> x = 'one',      # tuple
>>> x = 'one'.
Traceback (most recent call last):
SyntaxError: invalid syntax
>>> x = (12)        # int
>>> x = (1.2)       # float
>>> x = (1,2)       # tuple
>>> x = 1.,1.       # tuple
>>> x = 1.,.1       # tuple
>>> x = .1,1.       # tuple

5.2.6. Tuple or List

Both:

  • ordered

  • possible to getitem and slice

  • elements can be duplicated

  • elements of any types

Tuple:

  • immutable

  • one contingent block of data in memory

List:

  • mutable

  • implemented in memory as list of pointers to objects

  • objects are scattered in memory

Memory Footprint:

>>> from sys import getsizeof
>>>
>>> a = [1, 2, 3]
>>> b = (1, 2, 3)
>>>
>>> getsizeof(a)
120
>>>
>>> getsizeof(b)
64
../../_images/memory-tuple.png

Figure 5.1. Define tuple

../../_images/memory-list.png

Figure 5.2. Define list

../../_images/memory-all.png

Figure 5.3. Define str, tuple and list

5.2.7. Assignments

Code 5.4. Solution
"""
* Assignment: Sequence Tuple Create
* Required: yes
* Complexity: easy
* Lines of code: 1 lines
* Time: 2 min

English:
    1. Create tuple `result` with elements:
        a. `'a'`
        b. `1`
        c. `2.2`
    2. Run doctests - all must succeed

Polish:
    1. Stwórz tuple `result` z elementami:
        a. `'a'`
        b. `1`
        c. `2.2`
    2. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert result is not Ellipsis, 'Assignment solution must be in `result` instead of ... (Ellipsis)'
    >>> assert type(result) is tuple, 'Variable `result` has invalid type, should be tuple'
    >>> assert len(result) == 3, 'Variable `result` length should be 3'

    >>> 'a' in result
    True
    >>> 1 in result
    True
    >>> 2.2 in result
    True
"""

result = ...  # tuple[str|int|float]: with 'a' and 1 and 2.2

Code 5.5. Solution
"""
* Assignment: Sequence Tuple Select
* Required: yes
* Complexity: easy
* Lines of code: 1 lines
* Time: 5 min

English:
    1. Define `result: tuple` representing all species
    2. To convert table use multiline select with `alt` 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` 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

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert result is not Ellipsis, 'Assignment solution must be in `result` instead of ... (Ellipsis)'
    >>> 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 elements of setosa'
    >>> assert result.count('versicolor') == 2, 'Result should have 2 elements of versicolor'

    >>> ('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)
    True

"""

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 = ...  # tuple[str]: define a tuple with species names

Code 5.6. Solution
"""
* Assignment: Sequence Tuple Mean
* Required: no
* Complexity: medium
* Lines of code: 8 lines
* Time: 8 min

English:
    1. Calculate mean for each numerical values column
    2. To convert table use multiline select with `alt` key in your IDE
    3. Do not use `str.split()`, `slice`, `getitem`, `for`, `while` or any other control-flow statement
    4. Run doctests - all must succeed

Polish:
    1. Wylicz średnią arytmetyczną dla każdej z kolumn numerycznych
    2. Do konwersji tabelki wykorzystaj zaznaczanie wielu linijek za pomocą klawisza `alt` w Twoim IDE
    3. Nie używaj `str.split()`, `slice`, `getitem`, `for`, `while` lub jakiejkolwiek innej instrukcji sterującej
    4. 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

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> assert sepal_length is not Ellipsis, 'Assignment solution must be in `sepal_length` instead of ... (Ellipsis)'
    >>> assert sepal_width is not Ellipsis, 'Assignment solution must be in `sepal_width` instead of ... (Ellipsis)'
    >>> assert petal_length is not Ellipsis, 'Assignment solution must be in `petal_length` instead of ... (Ellipsis)'
    >>> assert petal_width is not Ellipsis, 'Assignment solution must be in `petal_width` instead of ... (Ellipsis)'
    >>> assert type(sepal_length) is float, 'Variable `sepal_length` has invalid type, should be float'
    >>> assert type(sepal_width) is float, 'Variable `sepal_width` has invalid type, should be float'
    >>> assert type(petal_length) is float, 'Variable `petal_length` has invalid type, should be float'
    >>> assert type(petal_width) is float, 'Variable `petal_width` has invalid type, should be float'

    >>> sepal_length
    5.859999999999999
    >>> sepal_width
    3.0200000000000005
    >>> petal_length
    4.14
    >>> petal_width
    1.34
"""

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',
]

sepal_length = ...  # float: arithmetic mean from tuple with 5.8, 5.1, 5.7, 6.3, 6.4
sepal_width = ...  # float: arithmetic mean from tuple with 2.7, 3.5, 2.8, 2.9, 3.2
petal_length = ...  # float: arithmetic mean from tuple with 5.1, 1.4, 4.1, 5.6, 4.5
petal_width = ...  # float: arithmetic mean from tuple with 1.9, 0.2, 1.3, 1.8, 1.5