5.1. Sequence List

5.1.1. Rationale

  • Mutable - can add, remove, and modify items

5.1.2. Definition

Defining empty list with [] is used more often, but list() is more explicit:

>>> data = list()
>>> data = []

Comma after last element is optional:

>>> data = [1]
>>> data = [1,]

Can store elements of any types:

>>> 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 required

>>> data = [1, 2, 3]

5.1.3. Type Casting

Builtin function list() converts argument to list

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

5.1.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.1.5. Set Item

>>> data = ['a', 'b', 'c', 'd']
>>> data[0] = 'x'
>>>
>>> print(data)
['x', 'b', 'c', 'd']
>>> data = ['a', 'b', 'c', 'd']
>>> data[4] = 'x'
Traceback (most recent call last):
IndexError: list assignment index out of range

5.1.6. Del Item

>>> data = ['a', 'b', 'c', 'd']
>>> del data[3]
>>>
>>> print(data)
['a', 'b', 'c']
>>> data = ['a', 'b', 'c', 'd']
>>> value = data.pop()
>>>
>>> data
['a', 'b', 'c']
>>> value
'd'

5.1.7. Append

  • list + list

  • list += list

  • list.extend()

  • list.append()

>>> [1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
>>> [1, 2, 3] + 4
Traceback (most recent call last):
TypeError: can only concatenate list (not "int") to list
>>> [1, 2, 3] + [4]
[1, 2, 3, 4]
>>> data = [1, 2, 3]
>>> data = data + [4, 5, 6]
>>>
>>> print(data)
[1, 2, 3, 4, 5, 6]
>>> data = [1, 2, 3]
>>> data += [4, 5, 6]
>>>
>>> print(data)
[1, 2, 3, 4, 5, 6]
>>> data = [1, 2, 3]
>>> data.extend([4, 5, 6])
>>>
>>> print(data)
[1, 2, 3, 4, 5, 6]
>>> data = [1, 2, 3]
>>> data.append(4)
>>>
>>> print(data)
[1, 2, 3, 4]
>>> data = [1, 2, 3]
>>> data.append([4, 5, 6])
>>>
>>> print(data)
[1, 2, 3, [4, 5, 6]]

5.1.8. Insert

  • Insert at specific position

>>> data = ['a', 'b', 'c', 'd']
>>> data.insert(0, 'x')
>>>
>>> print(data)
['x', 'a', 'b', 'c', 'd']
>>> data = ['a', 'b', 'c', 'd']
>>> data.insert(1, 'x')
>>>
>>> print(data)
['a', 'x', 'b', 'c', 'd']

5.1.9. Sort vs Sorted

Timsort is a hybrid stable sorting algorithm, derived from merge sort and insertion sort, designed to perform well on many kinds of real-world data. It was implemented by Tim Peters in 2002 for use in the Python programming language. The algorithm finds subsequences of the data that are already ordered (runs) and uses them to sort the remainder more efficiently. This is done by merging runs until certain criteria are fulfilled. Timsort has been Python's standard sorting algorithm since version 2.3. It is also used to sort arrays of non-primitive type in Java SE 7, on the Android platform, in GNU Octave, on V8, Swift, and Rust. 1

  • Worst-case performance: \(O(n\log{n})\)

  • Best-case performance: \(O(n)\)

  • Average performance: \(O(n\log{n})\)

  • Worst-case space complexity: \(O(n)\)

  • sorted() - Returns sorted list, do not modify the original

  • list.sort() - Changes object permanently, returns None

>>> data = [3, 1, 2]
>>> sorted(data)
[1, 2, 3]
>>> data = [3, 1, 2]
>>> data.sort()
>>> data
[1, 2, 3]
>>> data = ['a', 'c', 'b']
>>> sorted(data)
['a', 'b', 'c']

5.1.10. Method Chaining

>>> data = [3, 1, 2]
>>> data.sort()
>>> data.append(4)
>>>
>>> print(data)
[1, 2, 3, 4]
>>> data = [3, 1, 2]
>>>
>>> data.sort().append(4)
Traceback (most recent call last):
AttributeError: 'NoneType' object has no attribute 'append'

5.1.11. Built-in Functions

  • min() - Minimal value

  • max() - Maximal value

  • sum() - Sum of elements

  • len() - Length of a list

>>> data = [2, 0, 1]
>>>
>>> min(data)
0
>>> max(data)
2
>>> sum(data)
3
>>> len(data)
3
>>> data = ['a', 'c', 'b']
>>>
>>> min(data)
'a'
>>> max(data)
'c'
>>> sum(data)
Traceback (most recent call last):
TypeError: unsupported operand type(s) for +: 'int' and 'str'

5.1.12. Any, All

  • all() - All values are True

  • any() - Any values is True

>>> data = [True, False, True]
>>>
>>> any(data)
True
>>> all(data)
False

5.1.13. References

1

https://en.wikipedia.org/wiki/Timsort

5.1.14. Assignments

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

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

Polish:
    1. Stwórz listę `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, \
    'Assign result to variable: `result`'
    >>> assert type(result) is list, \
    'Variable `result` has invalid type, should be list'
    >>> assert len(result) == 3, \
    'Variable `result` length should be 3'

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

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

Code 5.2. Solution
"""
* Assignment: Sequence List Many
* Required: yes
* Complexity: easy
* Lines of code: 3 lines
* Time: 5 min

English:
    1. Create list `a` with data from row 1
    2. Create list `b` with data from row 2
    3. Create list `c` with data from row 3
    4. Rewrite data manually:
        a. Do not automate by writing code
        b. Do not use `str.split()`, `slice`, `getitem`, `for`, `while`
           or any other control-flow statement
        c. Objective is to learn the syntax, not automation
        d. Convert numerical values to float (manually)
    5. Run doctests - all must succeed

Polish:
    1. Stwórz listę `a` z danymi z wiersza 1
    2. Stwórz listę `b` z danymi z wiersza 2
    3. Stwórz listę `c` z danymi z wiersza 3
    4. Przepisz dane ręcznie:
        a. Nie automatyzuj pisząc kod
        b. Nie używaj `str.split()`, `slice`, `getitem`, `for`, `while`
           lub jakiejkolwiek innej instrukcji sterującej
        c. Celem jest nauka składni, a nie automatyzacja
        d. Przekonwertuj wartości numeryczne do float (ręcznie)
    5. Uruchom doctesty - wszystkie muszą się powieść

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

    >>> assert a is not Ellipsis, \
    'Assign result to variable: `a`'

    >>> assert b is not Ellipsis, \
    'Assign result to variable: `b`'

    >>> assert c is not Ellipsis, \
    'Assign result to variable: `c`'

    >>> assert type(a) is list, \
    'Variable `a` has invalid type, should be list'

    >>> assert type(b) is list, \
    'Variable `b` has invalid type, should be list'

    >>> assert type(c) is list, \
    'Variable `c` has invalid type, should be list'

    >>> assert len(a) == 5, \
    'Variable `a` length should be 5'

    >>> assert len(b) == 5, \
    'Variable `b` length should be 5'

    >>> assert len(c) == 5, \
    'Variable `c` length should be 5'

    >>> assert (5.8 in a
    ...     and 2.7 in a
    ...     and 5.1 in a
    ...     and 1.9 in a
    ...     and 'virginica' in a)

    >>> assert (5.1 in b
    ...     and 3.5 in b
    ...     and 1.4 in b
    ...     and 0.2 in b
    ...     and 'setosa' in b)

    >>> assert (5.7 in c
    ...     and 2.8 in c
    ...     and 4.1 in c
    ...     and 1.3 in c
    ...     and 'versicolor' in c)
"""

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

# list[float|str]: with data from row[1]: 5.8, 2.7, 5.1, 1.9 and virginica
a = ...

# list[float|str]: with data from row[2]: 5.1, 3.5, 1.4, 0.2 and setosa
b = ...

# list[float|str]: with data from row[3]: 5.7, 2.8, 4.1, 1.3 and versicolor
c = ...

Code 5.3. Solution
"""
* Assignment: Sequence List Modify
* Required: no
* Complexity: easy
* Lines of code: 3 lines
* Time: 5 min

English:
    1. Insert at the begin of `a` letter 'x'
    2. Append to the `b` last element popped from `a`
    3. For getting elements use `list.pop()`
    4. From list `c` using `del` delete last element
    5. Run doctests - all must succeed

Polish:
    1. Na początek `a` wstaw literę 'x'
    2. Na koniec `b` wstaw ostatni element wyciągnięty z `a`
    3. Do wyciągnięcia używaj `list.pop()`
    4. Z listy `c` za pomocą `del` usuń ostatni element
    5. Uruchom doctesty - wszystkie muszą się powieść

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

    >>> assert a is not Ellipsis, \
    'Assign result to variable: `a`'
    >>> assert b is not Ellipsis, \
    'Assign result to variable: `b`'
    >>> assert c is not Ellipsis, \
    'Assign result to variable: `c`'
    >>> assert type(a) is list, \
    'Variable `a` has invalid type, should be list'
    >>> assert type(b) is list, \
    'Variable `b` has invalid type, should be list'
    >>> assert type(c) is list, \
    'Variable `c` has invalid type, should be list'

    >>> a
    ['x', 4.7, 3.2, 1.3, 0.2]
    >>> b
    [7.0, 3.2, 4.7, 1.4, 'versicolor', 'setosa']
    >>> c
    [7.6, 3.0, 6.6, 2.1]
"""

a = [4.7, 3.2, 1.3, 0.2, 'setosa']
b = [7.0, 3.2, 4.7, 1.4, 'versicolor']
c = [7.6, 3.0, 6.6, 2.1, 'virginica']

# insert at the begin of `a` letter 'x'
# append to the `b` last element popped from `a`
# for getting elements use `list.pop()`
# from list `c` using `del` delete last element