5.8. Mapping Switch

  • No switch statement in Python!

  • switch in Object Oriented Programming is considered a bad practise

  • PEP 275 -- Switching on Multiple Values [Rejected]

  • Since Python 3.10: PEP 636 -- Structural Pattern Matching: Tutorial

5.8.1. Example

>>> hello = {
...    'English': 'Hello',
...    'German': 'Guten Tag',
...    'Polish': 'Witaj',
... }
>>>
>>>
>>> hello.get('English')
'Hello'
>>>
>>> hello.get('Polish')
'Witaj'

5.8.2. Dict Switch

Simulate user input (for test automation):

>>> from unittest.mock import MagicMock
>>> input = MagicMock(side_effect=['French'])
>>> hello = {
...     'English': 'Hello',
...     'German': 'Guten Tag',
...     'Polish': 'Witaj',
...     'default': "I don't speak this language",
... }
>>>
>>>
>>> language = input('What is your language?: ')  #input: 'French'
>>> result = hello.get(language, hello['default'])
>>>
>>> print(result)
I don't speak this language

5.8.3. Function Switch

>>> def hello(language):
...     data = {
...         'English': 'Hello',
...         'German': 'Guten Tag',
...         'Polish': 'Witaj',
...         'default': "I don't speak this language"}
...     return data.get(language, data['default'])
>>>
>>>
>>> hello('Polish')
'Witaj'
>>>
>>> hello('French')
"I don't speak this language"

5.8.4. Use Case - 0x01

>>> MONTHS = {
...     1: 'January',
...     2: 'February',
...     3: 'March',
... }
>>>
>>> MONTHS[1]
'January'
>>>
>>> MONTHS['1']
Traceback (most recent call last):
KeyError: '1'
>>>
>>> MONTHS['01']
Traceback (most recent call last):
KeyError: '01'

5.8.5. Use Case - 0x02

>>> MONTHS = {
...     1: 'January',
...     2: 'February',
...     3: 'March',
... }
>>>
>>> MONTHS.get(1)
'January'
>>>
>>> MONTHS.get(13)
>>>
>>> MONTHS.get(13, 'invalid month')
'invalid month'

5.8.6. Use Case - 0x03

>>> MONTHS = {
...     1: 'January',
...     2: 'February',
...     3: 'March',
...     4: 'April',
...     5: 'May',
...     6: 'June',
...     7: 'July',
...     8: 'August',
...     9: 'September',
...     10: 'October',
...     11: 'November',
...     12: 'December'
... }
>>>
>>> DATE = '1961-04-12'
>>>
>>> year, month, day = DATE.split('-')
>>>
>>> year
'1961'
>>> month
'04'
>>> day
'12'
>>>
>>> MONTHS[month]
Traceback (most recent call last):
KeyError: '04'
>>>
>>> MONTHS[int(month)]
'April'

5.8.7. Assignments

Code 5.4. Solution
"""
* Assignment: Mapping Switch Value
* Required: no
* Complexity: easy
* Lines of code: 2 lines
* Time: 3 min

English:
    1. Create translator of pilot's alphabet
    2. Each letter has it's phonetic counterpart
    3. Ask user to input letter
    4. User will always put only one capitalized letter or number
    5. Define `result: str` with phonetic letter pronunciation
    6. If character not existing in alphabet, print: 'Not found'
    7. Do not use `if`, `try`, and `except`
    8. `MagicMock` will simulate inputting a letter by user
    9. Use `input()` function as normal
    10. Run doctests - all must succeed

Polish:
    1. Stwórz tłumacza alfabetu pilotów
    2. Pojedynczym literom przyporządkuj ich fonetyczne odpowiedniki
    3. Poproś użytkownika o wprowadzenie litery
    4. Użytkownik zawsze poda tylko jedną dużą literę lub cyfrę
    5. Zdefiniuj `result: str` z fonetyczną wymową litery
    6. Jeżeli znak nie występuje w alfabecie, wypisz: 'Not found'
    7. Nie używaj `if`, `try` ani `except`
    8. `MagicMock` zasymuluje wpisanie litery przez użytkownika
    9. Skorzytaj z funkcji `input()` tak jak normalnie
    10. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `input()`

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

    >>> assert letter is not Ellipsis, \
    'Ask user to input letter and assign it to: `letter`'

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

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

    >>> result
    'Mike'
"""

from unittest.mock import MagicMock


# Simulate user input (for test automation)
input = MagicMock(side_effect=['M'])

ALPHABET = {
    'A': 'Alfa',
    'B': 'Bravo',
    'C': 'Charlie',
    'D': 'Delta',
    'E': 'Echo',
    'F': 'Foxtrot',
    'G': 'Golf',
    'H': 'Hotel',
    'I': 'India',
    'J': 'Juliet',
    'K': 'Kilo',
    'L': 'Lima',
    'M': 'Mike',
    'N': 'November',
    'O': 'Oscar',
    'P': 'Papa',
    'Q': 'Quebec',
    'R': 'Romeo',
    'S': 'Sierra',
    'T': 'Tango',
    'U': 'Uniform',
    'V': 'Victor',
    'W': 'Whisky',
    'X': 'X-Ray',
    'Z': 'Zulu',
}

# String with letter from user
# type: str
letter = ...

# String with converted letter to Pilot alphabet or 'Not found'
# type: str
result = ...

Code 5.5. Solution
"""
* Assignment: Mapping Switch Default
* Required: no
* Complexity: easy
* Lines of code: 2 lines
* Time: 5 min

English:
    1. Ask user to input single letter
    2. Convert to lowercase
    3. If letter is in `PL` then use conversion value as letter
    4. `MagicMock` will simulate inputting of a letter by user
    5. Use `input()` function as normal
    6. Run doctests - all must succeed

Polish:
    1. Poproś użytkownika o wprowadzenie jednej litery
    2. Przekonwertuj literę na małą
    3. Jeżeli litera jest w `PL` to użyj skonwertowanej wartości jako litera
    4. `MagicMock` zasymuluje wpisanie litery przez użytkownika
    5. Skorzytaj z funkcji `input()` tak jak normalnie
    6. Uruchom doctesty - wszystkie muszą się powieść

Hints:
    * `input()`
    * `str.lower()`

Example:
    | Input | Output |
    |-------|--------|
    |   A   |    a   |
    |   x   |    x   |
    |   Ł   |    ł   |
    |   ś   |    s   |
    |   Ź   |    z   |

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

    >>> assert letter is not Ellipsis, \
    'Ask user to input letter and assign it to: `letter`'

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

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

    >>> assert result not in PL.keys(), \
    'Result should not be in PL dict'

    >>> assert result in string.ascii_letters, \
    'Result should be an ASCII letter'
"""

from unittest.mock import MagicMock


# Simulate user input (for test automation)
input = MagicMock(side_effect=['Ł'])

PL = {'ą': 'a', 'ć': 'c', 'ę': 'e',
      'ł': 'l', 'ń': 'n', 'ó': 'o',
      'ś': 's', 'ż': 'z', 'ź': 'z'}

# String with letter from user
# type: str
letter = ...

# String with converted letter without PL diacritic chars
# type: str
result = ...