5.2. Mapping Define

5.2.1. Rationale

  • dict are key-value storage (HashMap)

  • Mutable - can add, remove, and modify items

  • Since Python 3.7: dict keeps order of elements

  • Before Python 3.7: dict order is not ensured!!

5.2.2. Syntax

  • {} is used more often

  • dict() is more readable

  • Comma after last element is optional

>>> data = {}
>>> data = dict()
>>> data = {
...    'commander': 'Melissa Lewis',
...    'botanist': 'Mark Watney',
...    'pilot': 'Rick Martinez',
... }
>>> data = dict(
...     commander='Melissa Lewis',
...     botanist='Mark Watney',
...     pilot='Rick Martinez',
... )

5.2.3. Duplicates

Duplicating items are overridden by latter:

>>> data = {
...     'commander': 'Melissa Lewis',
...     'commander': 'Jan Twardowski'
... }
>>>
>>> data
{'commander': 'Jan Twardowski'}

5.2.4. Dict vs Set

  • Both set and dict keys must be hashable

  • Both set and dict uses the same { and } braces

  • Despite similar syntax, they are different types

>>> data = {1, 2}
>>> type(data)
<class 'set'>
>>>
>>>
>>> data = {1: 2}
>>> type(data)
<class 'dict'>
>>> data = {1, 2, 3, 4}
>>> type(data)
<class 'set'>
>>>
>>>
>>> data = {1: 2, 3: 4}
>>> type(data)
<class 'dict'>

Empty dict and empty set:

>>> data = {1: None}
>>> _ = data.pop(1)
>>>
>>> data
{}
>>> data = {1}
>>> _ = data.pop()
>>>
>>> data
set()

5.2.5. Length

>>> crew = {
...    'commander': 'Melissa Lewis',
...    'botanist': 'Mark Watney',
...    'pilot': 'Rick Martinez'}
>>>
>>>
>>> len(crew)
3
>>>
>>> len(crew.keys())
3
>>>
>>> len(crew.values())
3
>>>
>>> len(crew.items())
3

5.2.6. Use Case - 0x1

  • GIT - version control system

>>> git = {
...    'ce16a8ce': 'commit/1',
...    'cae6b510': 'commit/2',
...    '895444a6': 'commit/3',
...    'aef731b5': 'commit/4',
...    '4a92bc79': 'branch/master',
...    'b3bbd85a': 'tag/v1.0'}

5.2.7. Assignments

Code 5.1. Solution
"""
* Assignment: Mapping Define Dict
* Required: yes
* Complexity: easy
* Lines of code: 3 lines
* Time: 3 min

English:
    1. Create `result: dict` representing input data
    2. Non-functional requirements:
        a. Assignmnet verifies creation of `dict()`
        b. Do not parse `DATA`, simply model `result` based on `DATA`
        c. Do not use `str.split()`, `slice`, `getitem`, `for`, `while` or
           any other control-flow statement
    3. Run doctests - all must succeed

Polish:
    1. Stwórz `result: dict` reprezentujący dane wejściowe
    2. Wymagania niefunkcjonalne:
        a. Zadanie sprawdza tworzenie `dict()`
        b. Nie parsuj `DATA`, po prostu zamodeluj `result` bazując na `DATA`
        c. Nie używaj `str.split()`, `slice`, `getitem`, `for`, `while` lub
           jakiejkolwiek innej instrukcji sterującej
    3. Uruchom doctesty - wszystkie muszą się powieść

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

    >>> assert type(result) is dict, \
    'Variable `result` has invalid type, should be dict'

    >>> assert 'First Name' in result.keys(), \
    'Value `First Name` is not in the result keys'

    >>> assert 'Last Name' in result.keys(), \
    'Value `Last Name` is not in the result keys'

    >>> assert 'Missions' in result.keys(), \
    'Value `Missions` is not in the result keys'

    >>> assert 'Jan' in result['First Name'], \
    'Value `Jan` is not in the result values'

    >>> assert 'Twardowski' in result['Last Name'], \
    'Value `Twardowski` is not in the result values'

    >>> assert 'Apollo' in result['Missions'], \
    'Value `Apollo` is not in the result values'

    >>> assert 'Artemis' in result['Missions'], \
    'Value `Artemis` is not in the result values'
"""

DATA = """
    First Name: Jan
    Last Name: Twardowski
    Missions: Apollo, Artemis
"""

# dict[str,str|list]: with First Name, Last Name and Missions as keys
result = ...