5.4. String Methods

  • str is immutable

  • str methods create a new modified str

5.4.1. Compare

  • str.casefold() - Return a version of the string suitable for caseless comparisons

>>> a = 'Alice'
>>> b = 'ALICE'
>>>
>>>
>>> a == b
False
>>>
>>> a.casefold() == b.casefold()
True

5.4.2. Change Case

  • str.upper() - all letters will be uppercase

  • str.lower() - all letters will be lowercase

  • str.capitalize() - will uppercase first letter of text, lowercase others

  • str.title() - will uppercase first letter of each word, lowercase others

  • str.swapcase() - make lowercase letters upper, and uppercase lower

>>> name = 'Angus MacGyver III'
>>>
>>> name.upper()
'ANGUS MACGYVER III'
>>>
>>> name.lower()
'angus macgyver iii'
>>>
>>> name.title()
'Angus Macgyver Iii'
>>>
>>> name.capitalize()
'Angus macgyver iii'
>>>
>>> name.swapcase()
'aNGUS mACgYVER iii'

5.4.3. Strip Whitespace

  • str.strip() - remove whitespaces from both ends

  • str.lstrip() - remove whitespaces from left side only

  • str.rstrip() - remove whitespaces from right side only

  • Whitespace characters: space (`` ), newline (n``), tab (\t)

Strip is a very common method, which you should always call upon any text from user input, that is from input() function, but also from files, socket communication and from internet data transfer. You never know, if the user did not pasted text from other source, which will add whitespace at the end of at the beginning of a string.

There are three strip methods: left strip, right strip and strip from both ends. Word whitespace refers to:

  • \n - newline

  • \t - tab

  • `` `` - space

  • \v - vertical space

  • \f - form-feed

Most common is plain strip, which will remove all whitespace characters from both sides at the same time:

>>> name = '  Alice  '
>>>
>>> name.strip()
'Alice'
>>>
>>> name.lstrip()
'Alice  '
>>>
>>> name.rstrip()
'  Alice'

5.4.4. Strip Characters

  • str.strip() - remove whitespaces from both ends

  • str.lstrip() - remove whitespaces from left side only

  • str.rstrip() - remove whitespaces from right side only

>>> text = '[ERROR]'
>>>
>>> text.strip('[]')
'ERROR'
>>>
>>> text.lstrip('[')
'ERROR]'
>>>
>>> text.rstrip(']')
'[ERROR'

5.4.5. Replace, Removeprefix, Removesuffix

  • str.replace()

  • str.removesuffix()

  • str.removeprefix()

>>> name = 'Alice'
>>>
>>> name.replace('A', 'X')
'Xlice'
>>>
>>> name.replace('a', 'X')
'Alice'
>>>
>>> name.removeprefix('Al')
'ice'
>>>
>>> name.removesuffix('ce')
'Ali'

5.4.6. Startswith, Endswith

  • str.startswith() - return True if str starts with the specified prefix, False otherwise

  • str.endswith() - return True if str ends with the specified suffix, False otherwise

  • optional start, test str beginning at that position

  • optional end, stop comparing str at that position

  • prefix/suffix can also be a tuple of strings to try

>>> email = 'alice@example.com'
>>>
>>> email.startswith('alice')
True
>>>
>>> email.startswith(('alice', 'bob'))
True
>>>
>>> email.endswith('example.com')
True
>>>
>>> email.endswith(('example.com', 'example.net'))
True

5.4.7. Split by Character

  • str.split() - Split by given character

  • str.split(sep, maxsplit=3) - split by max number of splits

  • No argument - any number of whitespaces

>>> data = 'Alice,Bob,Carol'
>>>
>>> data.split(',')
['Alice', 'Bob', 'Carol']

5.4.8. Split by Space

  • str.split() - Split by given character

  • str.split(sep, maxsplit=3) - split by max number of splits

  • Whitespace characters: space (`` ), newline (n``), tab (\t)

>>> data = 'Alice Bob Carol'
>>>
>>> data.split()
['Alice', 'Bob', 'Carol']
>>>
>>> data.split(' ')
['Alice', 'Bob', 'Carol']

Example with separator:

>>> data = 'Alice    Bob    Carol'
>>>
>>> data.split()
['Alice', 'Bob', 'Carol']
>>>
>>> data.split(None)
['Alice', 'Bob', 'Carol']
>>>
>>> data.split(' ')
['Alice', '', '', '', 'Bob', '', '', '', 'Carol']

Example with maxsplit:

>>> data = '2000-01-01 12:00:00 ERROR Unexpected behavior happened'
>>>
>>> data.split()
['2000-01-01', '12:00:00', 'ERROR', 'Unexpected', 'behavior', 'happened']
>>>
>>> data.split(maxsplit=3)
['2000-01-01', '12:00:00', 'ERROR', 'Unexpected behavior happened']

5.4.9. Split by Line

  • str.splitlines() - split by newline character, don't leave empty lines at the end

  • str.split('\n') - will leave empty string if newline is a the end of str

>>> text = 'Alice\nBob\nCarol'
>>>
>>> text.splitlines()
['Alice', 'Bob', 'Carol']
>>>
>>> text.split('\n')
['Alice', 'Bob', 'Carol']

Longer text:

>>> text = """Lorem ipsum dolor sit amet, consectetur adipiscing elit,
... sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
... Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
... nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
... reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
... pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
... culpa qui officia deserunt mollit anim id est laborum."""
>>>
>>>
>>> text.splitlines()
['Lorem ipsum dolor sit amet, consectetur adipiscing elit,',
 'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris',
 'nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in',
 'reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla',
 'pariatur. Excepteur sint occaecat cupidatat non proident, sunt in',
 'culpa qui officia deserunt mollit anim id est laborum.']

5.4.10. Join by Character

  • [1]

  • str.join(sep, sequence) - concatenate sequence using separator

  • Note, this is a method of a str, not tuple.join() or list.join()

>>> names = ['Alice', 'Bob', 'Carol']
>>>
>>> ','.join(names)
'Alice,Bob,Carol'
>>>
>>> ';'.join(names)
'Alice;Bob;Carol'
>>>
>>> ' '.join(names)
'Alice Bob Carol'
>>>
>>> '\n'.join(names)
'Alice\nBob\nCarol'

5.4.11. Is Whitespace

  • str.isspace() - Is whitespace

  • Whitespace characters: space (`` ), newline (n``), tab (\t)

>>> data = ' '
>>> data.isspace()
True
>>>
>>> data = '\t'
>>> data.isspace()
True
>>>
>>> data = '\n'
>>> data.isspace()
True
>>>
>>> data = ''
>>> data.isspace()
False

5.4.12. Is Alphabet Characters

  • str.isalpha()

>>> text = 'hello'
>>> text.isalpha()
True
>>> text = 'hello1'
>>> text.isalpha()
False

5.4.13. Is Numeric

>>> '1'.isdecimal()
True
>>>
>>> '+1'.isdecimal()
False
>>>
>>> '-1'.isdecimal()
False
>>>
>>> '1.'.isdecimal()
False
>>>
>>> '1,'.isdecimal()
False
>>>
>>> '1.0'.isdecimal()
False
>>>
>>> '1,0'.isdecimal()
False
>>>
>>> '1_0'.isdecimal()
False
>>>
>>> '10'.isdecimal()
True
>>> '1'.isdigit()
True
>>>
>>> '+1'.isdigit()
False
>>>
>>> '-1'.isdigit()
False
>>>
>>> '1.'.isdigit()
False
>>>
>>> '1,'.isdigit()
False
>>>
>>> '1.0'.isdigit()
False
>>>
>>> '1,0'.isdigit()
False
>>>
>>> '1_0'.isdigit()
False
>>>
>>> '10'.isdigit()
True
>>> '1'.isnumeric()
True
>>>
>>> '+1'.isnumeric()
False
>>>
>>> '-1'.isnumeric()
False
>>>
>>> '1.'.isnumeric()
False
>>>
>>> '1.0'.isnumeric()
False
>>>
>>> '1,0'.isnumeric()
False
>>>
>>> '1_0'.isnumeric()
False
>>>
>>> '10'.isnumeric()
True
>>> '1'.isalnum()
True
>>>
>>> '+1'.isalnum()
False
>>>
>>> '-1'.isalnum()
False
>>>
>>> '1.'.isalnum()
False
>>>
>>> '1,'.isalnum()
False
>>>
>>> '1.0'.isalnum()
False
>>>
>>> '1,0'.isalnum()
False
>>>
>>> '1_0'.isalnum()
False
>>>
>>> '10'.isalnum()
True

5.4.14. Find Sub-String Position

  • str.find() - Finds position of a letter in text

  • Case sensitive

  • Computers start counting from 0

  • Returns -1 if not found

>>> name = 'Alice'
>>>
>>> name.find('A')
0
>>>
>>> name.find('a')
-1
>>>
>>> name.find('ice')
2

5.4.15. Count Occurrences

  • str.count()

  • returns 0 if not found

>>> text = 'Moon'
>>>
>>>
>>> text.count('m')
0
>>>
>>> text.count('M')
1
>>>
>>> text.count('o')
2

5.4.16. Method Chaining

>>> name = 'Angus MacGyver 3'
>>> result = name.lower().replace('mac', 'mc').replace('3', 'III').strip().title()
>>> name = 'Angus MacGyver 3'
>>>
>>> result = (
...     name
...     .lower()
...     .replace('mac', 'mc')
...     .replace('3', 'III')
...     .replace('2', 'II')
...     .replace('1', 'I')
...     .strip()
...     .title()
... )

5.4.17. Use Case - 1

Replace substring:

>>> name = 'Angus MacGyver Iii'
>>> name.replace('Iii', 'III')
'Angus MacGyver III'

Replace is case sensitive:

>>> name = 'Angus MacGyver Iii'
>>> name.replace('iii', 'III')
'Angus MacGyver Iii'

5.4.18. Use case - 2

>>> filename = '5.05-assignment-a.py'
>>>
>>> filename.removeprefix('5.05-')
'assignment-a.py'
>>>
>>> filename.removesuffix('.py')
'5.05-assignment-a'
>>>
>>> filename.removeprefix('5.05-').removesuffix('.py')
'assignment-a'

5.4.19. Use Case - 3

>>> data = 'Alice,30,alice@example.com\n'
>>>
>>> data.split(',')
['Alice', '30', 'alice@example.com\n']
>>>
>>> data.strip().split(',')
['Alice', '30', 'alice@example.com']

5.4.20. Use Case - 4

>>> data = ['Alice', '30', 'alice@example.com']
>>>
>>> ','.join(data)
'Alice,30,alice@example.com'
>>>
>>> ','.join(data) + '\n'
'Alice,30,alice@example.com\n'

5.4.21. Use Case - 5

>>> lvl = '[WARNING]'
>>> lvl.removeprefix('[').removesuffix(']')
'WARNING'
>>> lvl = '[WARNING]'
>>> lvl.replace('[', '').replace(']', '')
'WARNING'
>>> lvl = '[WARNING]'
>>> lvl.strip('[]')
'WARNING'

5.4.22. Use Case - 6

>>> line = '1969-07-21,02:56:15,WARNING,First step on the Moon'
>>>
>>> line.split(',', maxsplit=3)
['1969-07-21', '02:56:15', 'WARNING', 'First step on the Moon']

5.4.23. Use Case - 7

>>> line = '1969-07-21 02:56:15.123 [WARNING] First step on the Moon'
>>> d, t, lvl, msg = line.split(maxsplit=3)
>>> d
'1969-07-21'
>>> t
'02:56:15.123'
>>> lvl.strip('[]')
'WARNING'
>>> msg.title()
'First Step On The Moon'

5.4.24. Use Case - 8

>>> DATA = """1969-07-14, 21:00:00, INFO, Terminal countdown started
... 1969-07-16, 13:31:53, WARNING, S-IC engine ignition (#5)
... 1969-07-16, 13:33:23, DEBUG, Maximum dynamic pressure (735.17 lb/ft^2)
... 1969-07-16, 13:34:44, WARNING, S-II ignition
... 1969-07-16, 13:35:17, DEBUG, Launch escape tower jettisoned
... 1969-07-16, 13:39:40, DEBUG, S-II center engine cutoff
... 1969-07-16, 16:22:13, INFO, Translunar injection
... 1969-07-16, 16:56:03, INFO, CSM docked with LM/S-IVB
... 1969-07-16, 17:21:50, INFO, Lunar orbit insertion ignition
... 1969-07-16, 21:43:36, INFO, Lunar orbit circularization ignition
... 1969-07-20, 17:44:00, INFO, CSM/LM undocked
... 1969-07-20, 20:05:05, WARNING, LM powered descent engine ignition
... 1969-07-20, 20:10:22, ERROR, LM 1202 alarm
... 1969-07-20, 20:14:18, ERROR, LM 1201 alarm
... 1969-07-20, 20:17:39, WARNING, LM lunar landing
... 1969-07-21, 02:39:33, DEBUG, EVA started (hatch open)
... 1969-07-21, 02:56:15, WARNING, 1st step taken lunar surface (CDR)
... 1969-07-21, 02:56:15, WARNING, Neil Armstrong first words on the Moon
... 1969-07-21, 03:05:58, DEBUG, Contingency sample collection started (CDR)
... 1969-07-21, 03:15:16, INFO, LMP on lunar surface
... 1969-07-21, 05:11:13, DEBUG, EVA ended (hatch closed)
... 1969-07-21, 17:54:00, WARNING, LM lunar liftoff ignition (LM APS)
... 1969-07-21, 21:35:00, INFO, CSM/LM docked
... 1969-07-22, 04:55:42, WARNING, Transearth injection ignition (SPS)
... 1969-07-24, 16:21:12, INFO, CM/SM separation
... 1969-07-24, 16:35:05, WARNING, Entry
... 1969-07-24, 16:50:35, WARNING, Splashdown (went to apex-down)
... 1969-07-24, 17:29, INFO, Crew egress"""
>>>
>>> DATA.splitlines()
['1969-07-14, 21:00:00, INFO, Terminal countdown started',
 '1969-07-16, 13:31:53, WARNING, S-IC engine ignition (#5)',
 '1969-07-16, 13:33:23, DEBUG, Maximum dynamic pressure (735.17 lb/ft^2)',
 '1969-07-16, 13:34:44, WARNING, S-II ignition',
 '1969-07-16, 13:35:17, DEBUG, Launch escape tower jettisoned',
 '1969-07-16, 13:39:40, DEBUG, S-II center engine cutoff',
 '1969-07-16, 16:22:13, INFO, Translunar injection',
 '1969-07-16, 16:56:03, INFO, CSM docked with LM/S-IVB',
 '1969-07-16, 17:21:50, INFO, Lunar orbit insertion ignition',
 '1969-07-16, 21:43:36, INFO, Lunar orbit circularization ignition',
 '1969-07-20, 17:44:00, INFO, CSM/LM undocked',
 '1969-07-20, 20:05:05, WARNING, LM powered descent engine ignition',
 '1969-07-20, 20:10:22, ERROR, LM 1202 alarm',
 '1969-07-20, 20:14:18, ERROR, LM 1201 alarm',
 '1969-07-20, 20:17:39, WARNING, LM lunar landing',
 '1969-07-21, 02:39:33, DEBUG, EVA started (hatch open)',
 '1969-07-21, 02:56:15, WARNING, 1st step taken lunar surface (CDR)',
 '1969-07-21, 02:56:15, WARNING, Neil Armstrong first words on the Moon',
 '1969-07-21, 03:05:58, DEBUG, Contingency sample collection started (CDR)',
 '1969-07-21, 03:15:16, INFO, LMP on lunar surface',
 '1969-07-21, 05:11:13, DEBUG, EVA ended (hatch closed)',
 '1969-07-21, 17:54:00, WARNING, LM lunar liftoff ignition (LM APS)',
 '1969-07-21, 21:35:00, INFO, CSM/LM docked',
 '1969-07-22, 04:55:42, WARNING, Transearth injection ignition (SPS)',
 '1969-07-24, 16:21:12, INFO, CM/SM separation',
 '1969-07-24, 16:35:05, WARNING, Entry',
 '1969-07-24, 16:50:35, WARNING, Splashdown (went to apex-down)',
 '1969-07-24, 17:29, INFO, Crew egress']

5.4.25. Use Case - 9

>>> DATA = 'ul. pANA tWARdoWSKiego 3'
>>>
>>> result = (
...     DATA
...
...     # Normalize
...     .upper()
...
...     # Remove whitespace control chars
...     .replace('\n', ' ')
...     .replace('\t', ' ')
...     .replace('\v', ' ')
...     .replace('\f', ' ')
...
...     # Remove whitespaces
...     .replace('    ', ' ')
...     .replace('   ', ' ')
...     .replace('  ', ' ')
...
...     # Remove special characters
...     .replace('$', '')
...     .replace('@', '')
...     .replace('#', '')
...     .replace('^', '')
...     .replace('&', '')
...     .replace('.', '')
...     .replace(',', '')
...     .replace('|', '')
...
...     # Remove prefixes
...     .removeprefix('ULICA')
...     .removeprefix('UL')
...     .removeprefix('OSIEDLE')
...     .removeprefix('OS')
...
...     # Substitute
...     .replace('3', 'III')
...     .replace('2', 'II')
...     .replace('1', 'I')
...
...     # Format output
...     .title()
...     .replace('Iii', 'III')
...     .replace('Ii', 'II')
...     .strip()
... )
>>>
>>> print(result)
Pana Twardowskiego III

5.4.26. References

5.4.27. Assignments

# %% About
# - Name: Type Str Splitlines
# - Difficulty: easy
# - Lines: 1
# - Minutes: 2

# %% 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. Split `DATA` by lines
# 2. Run doctests - all must succeed

# %% Polish
# 1. Podziel `DATA` po liniach
# 2. Uruchom doctesty - wszystkie muszą się powieść

# %% 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 len(result) == 3, \
'Variable `result` length should be 3'
>>> assert type(result) is list, \
'Variable `result` has invalid type, should be list'

>>> line = 'We choose to go to the Moon'
>>> assert line in result, f'Line "{line}" is not in the result'

>>> line = 'in this decade and do the other things.'
>>> assert line in result, f'Line "{line}" is not in the result'

>>> line = 'Not because they are easy, but because they are hard.'
>>> assert line in result, f'Line "{line}" is not in the 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: list[str]

# %% Data
DATA = """We choose to go to the Moon
in this decade and do the other things.
Not because they are easy, but because they are hard."""

# %% Result
result = ...

# %% About
# - Name: Type Str Join
# - 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. Join lines of text with newline (`\n`) character
# 2. Run doctests - all must succeed

# %% Polish
# 1. Połącz linie tekstu znakiem końca linii (`\n`)
# 2. Uruchom doctesty - wszystkie muszą się powieść

# %% Hints
# - `str.join()`

# %% 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 str, \
'Variable `result` has invalid type, should be str'
>>> assert result.count('\\n') == 2, \
'There should be only two newline characters in result'

>>> line = 'We choose to go to the Moon'
>>> assert line in result, f'Line "{line}" is not in the result'

>>> line = 'in this decade and do the other things.'
>>> assert line in result, f'Line "{line}" is not in the result'

>>> line = 'Not because they are easy, but because they are hard.'
>>> assert line in result, f'Line "{line}" is not in the 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: str

# %% Data
DATA = [
    'We choose to go to the Moon',
    'in this decade and do the other things.',
    'Not because they are easy, but because they are hard.',
]

# %% Result
result = ...

# %% About
# - Name: Type Str Normalize
# - Difficulty: easy
# - Lines: 4
# - 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. Use `str` methods to clean `DATA`
#    Expected: 'Pana Twardowskiego III'
# 2. Run doctests - all must succeed

# %% Polish
# 1. Wykorzystaj metody `str` do oczyszczenia `DATA`
#    Oczekiwane: 'Pana Twardowskiego III'
# 2. Uruchom doctesty - wszystkie muszą się powieść

# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> from pprint import pprint

>>> assert result is not Ellipsis, \
'Assign your result to variable `result`'
>>> assert type(result) is str, \
'Variable `result` has invalid type, should be str'

>>> pprint(result)
'Pana Twardowskiego III'
"""

# %% 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: str

# %% Data
DATA = 'UL. pana \tTWArdoWskIEGO 3'

# %% Result
result = ...

# %% About
# - Name: Type Str Normalization
# - Difficulty: easy
# - Lines: 8
# - Minutes: 13

# %% 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. Use `str` methods to clean `DATA`
#    Expected: 'Pana Twardowskiego III'
# 2. Run doctests - all must succeed

# %% Polish
# 1. Wykorzystaj metody `str` do oczyszczenia `DATA`
#    Oczekiwane: 'Pana Twardowskiego III'
# 2. Uruchom doctesty - wszystkie muszą się powieść

# %% Doctests
"""
>>> import sys; sys.tracebacklimit = 0
>>> assert sys.version_info >= (3, 9), \
'Python 3.9+ required'

>>> assert example is not Ellipsis, \
'Assign your result to variable `example`'
>>> assert result_a is not Ellipsis, \
'Assign your result to variable `a`'
>>> assert result_b is not Ellipsis, \
'Assign your result to variable `b`'
>>> assert result_c is not Ellipsis, \
'Assign your result to variable `c`'
>>> assert result_d is not Ellipsis, \
'Assign your result to variable `d`'
>>> assert result_e is not Ellipsis, \
'Assign your result to variable `e`'
>>> assert result_f is not Ellipsis, \
'Assign your result to variable `f`'
>>> assert result_g is not Ellipsis, \
'Assign your result to variable `g`'

>>> assert type(example) is str, \
'Variable `example` has invalid type, should be str'
>>> assert type(result_a) is str, \
'Variable `result_a` has invalid type, should be str'
>>> assert type(result_b) is str, \
'Variable `result_b` has invalid type, should be str'
>>> assert type(result_c) is str, \
'Variable `result_c` has invalid type, should be str'
>>> assert type(result_d) is str, \
'Variable `result_d` has invalid type, should be str'
>>> assert type(result_e) is str, \
'Variable `result_e` has invalid type, should be str'
>>> assert type(result_f) is str, \
'Variable `result_f` has invalid type, should be str'
>>> assert type(result_g) is str, \
'Variable `result_g` has invalid type, should be str'

>>> example
'Pana Twardowskiego III'
>>> result_a
'Pana Twardowskiego III'
>>> result_b
'Pana Twardowskiego III'
>>> result_c
'Pana Twardowskiego III'
>>> result_d
'Pana Twardowskiego III'
>>> result_e
'Pana Twardowskiego III'
>>> result_f
'Pana Twardowskiego III'
>>> result_g
'Pana Twardowskiego III'
"""

# %% 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: str
result_b: str
result_c: str
result_d: str
result_e: str
result_f: str
result_g: str

# %% Data
EXAMPLE = 'UL. Pana \tTWArdoWskIEGO 3'

A = 'ulica Pana Twardowskiego III'
B = 'ul Pana Twardowskiego III'
C = 'ul. Pana Twardowskiego III'
D = 'Pana Twardowskiego 3'
E = ' Pana Twardowskiego III\t'
F = 'Pana\t Twardowskiego III'
G = 'Pana Twardowskiego III\n'

example = (
    EXAMPLE
    .upper()
    .replace('UL. ', '')
    .replace('\t', '')
    .strip()
    .title()
    .replace('3', 'III')
)

# %% Result
result_a = ...
result_b = ...
result_c = ...
result_d = ...
result_e = ...
result_f = ...
result_g = ...