1. Function Basics

1.1. Function definition

  • Wielokrotne używanie tego samego kodu
  • Poprawiają czytelność kodu
  • Porządkują kod
  • Pozwalają na łatwiejszy refactoring
def hello():
    print('My name... José Jiménez')

hello()     # My name... José Jiménez
hello()     # My name... José Jiménez
hello()     # My name... José Jiménez

1.2. Returning values

  • return wskazuje funkcji jaką wartość ma zwrócić
  • Kod po słowie kluczowym return się nie wykona
def hello():
    return 'ehlo world'

output = hello()

print(output)
# 'ehlo world'
def hello():
    return 'ehlo world'
    print('This will not be executed')

output = hello()

print(output)
# 'ehlo world'

1.2.1. Returning simple types

def function():
    return 42
def function():
    return 13.37
def function():
    return 'José Jiménez'
def function():
    return (42, 13.37, 'José Jiménez')
def function():
    return 42, 13.37, 'José Jiménez'
def function():
    return [42, 13.37, 'foobar']
def function():
    return {42, 13.37, 'José Jiménez'}
def function():
    return {'first_name': 'José', 'last_name': 'Jiménez'}
def function():
    return True
def function():
    return None
def function():
    print('ehlo world')
    # Python will ``return None`` if not specified
def function():
    pass
    # Python will ``return None`` if not specified

1.2.2. Returning nested types

def function():
    return [
        ('Mark', 'Watney'),
        {'Pan Twardowski', 'Melissa Lewis'},
        {'astro': 'Иванович', 'agency': {'name': 'Roscosmos'}},
        {'astro': 'Jiménez', 'missions': ('Mercury', 'Apollo')},
    ]

1.3. Function arguments

1.3.1. Passing arguments

def add(a, b):
    return a + b

add(1, 2)
# 3

1.3.2. Named arguments

def minus(a, b):
    return a - b

minus(2, 1)      # 1
minus(1, 2)      # -1
minus(a=2, b=1)  # 1
minus(b=1, a=2)  # 1
minus(2, b=1)    # 1
minus(a=2, 1)    # SyntaxError: positional argument follows keyword argument

1.3.3. Arguments with default value

  • Funkcja przyjmie wartość domyślną dla argumentu jeżeli użytkownik nie nadpisze
  • Argumenty z wartością domyślną muszą być skrajnie po prawej stronie
  • Kolejność podawania argumentów nazwanych nie ma znaczenia
  • Argumenty z wartościami domyślnymi nie muszą być podane
  • Arguemnty bez wartości domyślnych są wymagane
def hello(name='José Jiménez'):
     print(f'My name... {name}')


hello('Иван Иванович')        # My name... Иван Иванович
hello(name='Иван Иванович')   # My name... Иван Иванович
hello()                       # My name... José Jiménez
def server(username, password, host='127.0.0.1',
           port=80, ssl=False, keep_alive=1,
           persistent=False):
    print('Connecting...')


server('admin', 'admin', 'localhost', 80, False, 1, True)

server(host='localhost', username='admin', password='admin', ssl=True, keep_alive=1, persistent=True)

server(
    host='localhost',
    username='admin',
    password='admin',
    port=443,
    ssl=True,
    persistent=True,
)
# ``read_csv`` is a function from ``pandas`` library
read_csv(filepath_or_buffer, sep=', ', delimiter=None,
         header='infer', names=None, index_col=None,
         usecols=None, squeeze=False, prefix=None,
         mangle_dupe_cols=True, dtype=None, engine=None,
         converters=None, true_values=None, false_values=None,
         skipinitialspace=False, skiprows=None, nrows=None,
         na_values=None, keep_default_na=True, na_filter=True,
         verbose=False, skip_blank_lines=True, parse_dates=False,
         infer_datetime_format=False, keep_date_col=False,
         date_parser=None, dayfirst=False, iterator=False,
         chunksize=None, compression='infer', thousands=None,
         decimal=b'.', lineterminator=None, quotechar='"',
         quoting=0, escapechar=None, comment=None, encoding=None,
         dialect=None, tupleize_cols=None, error_bad_lines=True,
         warn_bad_lines=True, skipfooter=0, doublequote=True,
         delim_whitespace=False, low_memory=True, memory_map=False,
         float_precision=None)


data = read_csv(
    filepath_or_buffer='iris.csv',
    encoding='utf-8',
    usecols=['Petal lenght', 'Species']
)

1.4. Naming convention

1.4.1. Function name convention

  • It’s not Java, do not use camelCase

    def addNumbers(a, b):
        return a + b
    
  • It’s Python, use snake_case # Python - snake ;)

    def add_numbers(a, b):
        return a + b
    

1.4.2. Use better names, rather than comments

def cal_var(results):
    """Calculate variance"""
    return sum((Xi-m) ** 2 for Xi in results) / len(results)

def calculate_variance(results):
    return sum((Xi-m) ** 2 for Xi in results) / len(results)

1.4.3. Name collisions

  • _ at the end of name when name collision

    def print_(text):
        print(f'<strong>{text}</strong>')
    

1.4.4. System functions names

  • __ at the beginning and end of name

    def __import__(module_name):
        ...
    

1.5. Variable scope

  • function arguemnts and variables live only inside function scope
  • globals() - all variables in program (outside functions)
  • locals() - variables inside function
def add(a, b=2):
    c = 3
    print(locals())

add(1)
# {'a': 1, 'b': 2, 'c': 3}

1.6. More advanced topics

Note

The topic will be continued in Advanced Functions chapter

1.7. Assignments

1.7.1. Cleaning text input

  • Filename: functions_str_clean.py
  • Lines of code to write: 15 lines
  • Estimated time of completion: 15 min
  1. Napisz funkcję oczyszczającą, która podane niżej zmienne zamieni na ciąg “Jana III Sobieskiego”
expected = 'Jana III Sobieskiego'

a = '  Jana III Sobieskiego '
b = 'ul Jana III SobIESkiego'
c = '\tul. Jana trzeciego Sobieskiego'
d = 'ulicaJana III Sobieskiego'
e = 'UL. JA\tNA 3 SOBIES\tKIEGO'
f = 'UL. jana III SOBiesKIEGO'
g = 'ULICA JANA III SOBIESKIEGO  '
h = 'ULICA. JANA III SOBIeskieGO'
i = ' Jana 3 Sobieskiego  '
j = 'Jana III\tSobieskiego '
k = 'ul.Jana III Sob\n\nieskiego\n'

print(f'{a == expected}\t a: "{a}"')
print(f'{b == expected}\t b: "{b}"')
print(f'{c == expected}\t c: "{c}"')
print(f'{d == expected}\t d: "{d}"')
print(f'{e == expected}\t e: "{e}"')
print(f'{f == expected}\t f: "{f}"')
print(f'{g == expected}\t g: "{g}"')
print(f'{h == expected}\t h: "{h}"')
print(f'{i == expected}\t i: "{i}"')
print(f'{j == expected}\t j: "{j}"')
print(f'{k == expected}\t k: "{k}"')
The whys and wherefores:
 
  • Definiowanie i uruchamianie funkcji
  • Sprawdzanie przypadków brzegowych (niekompatybilne argumenty)
  • Parsowanie argumentów funkcji
  • Czyszczenie danych od użytkownika

1.7.2. Aviation numbers

  • Filename: functions_aviation_numbers.py
  • Lines of code to write: 15 lines
  • Estimated time of completion: 15 min
  1. Napisz funkcję aviation_numbers
  2. Funkcja zamieni dowolnego int lub float na formę tekstową w mowie pilotów
Tab. 1.2. Aviation Phonetic Numbers
Letter Pronounce
0 zero
1 one
2 two
3 tree
4 fower
5 fife
6 six
7 seven
8 ait
9 niner
def aviation_numbers(number):
    """
    >>> aviation_numbers(1969)
    'one niner six niner'

    >>> aviation_numbers(31337)
    'tree one tree tree seven'

    >>> aviation_numbers(13.37)
    'one tree and tree seven'

    >>> aviation_numbers(31.337)
    'tree one and tree tree seven'

    >>> aviation_numbers(-1969)
    'minus one niner six niner'

    >>> aviation_numbers(-31.337)
    'minus tree one and tree tree seven

    >>> aviation_numbers(-49.35)
    'minus fower niner and tree fife'
    """
    return
The whys and wherefores:
 
  • Definiowanie i uruchamianie funkcji
  • Sprawdzanie przypadków brzegowych (niekompatybilne argumenty)
  • Parsowanie argumentów funkcji
  • Definiowanie i korzystanie z dict z wartościami
  • Przypadek zaawansowany: argumenty pozycyjne i domyślne
  • Rzutowanie i konwersja typów

1.7.3. Number to human readable

  • Filename: functions_numstr_human.py
  • Lines of code to write: 15 lines
  • Estimated time of completion: 15 min
  1. Napisz funkcję number_to_str

  2. Funkcja zamieni dowolnego int lub float na formę tekstową

  3. Funkcja musi zmieniać wartości na poprawną gramatycznie formę

  4. Max 6 cyfr przed przecinkiem

  5. Max 5 cyfr po przecinku

    number_to_str(1969)      #
    number_to_str(13.37)     #
    number_to_str(31337)     #
    number_to_str(31.337)    #
    number_to_str(-1969)     #
    number_to_str(-31.337)   #
    
def aviation_numbers(number):
    """
    >>> aviation_numbers(1969)
    'one thousand nine hundred sixty nine'

    >>> aviation_numbers(31337)
    'thirty one thousand three hundred thirty seven'

    >>> aviation_numbers(13.37)
    'thirteen and thirty seven hundredths'

    >>> aviation_numbers(31.337)
    'thirty one three hundreds thirty seven thousands'

    >>> aviation_numbers(-1969)
    'minus one thousand nine hundred sixty nine'

    >>> aviation_numbers(-31.337)
    'minus thirty one three hundreds thirty seven thousands'

    >>> aviation_numbers(-49.35)
    'minus fower niner and tree fife'
    """
    return
The whys and wherefores:
 
  • Definiowanie i uruchamianie funkcji
  • Sprawdzanie przypadków brzegowych (niekompatybilne argumenty)
  • Parsowanie argumentów funkcji
  • Definiowanie i korzystanie z dict z wartościami
  • Przypadek zaawansowany: argumenty pozycyjne i domyślne
  • Rzutowanie i konwersja typów

1.7.4. Roman numbers

  • Filename: functions_roman.py
  • Lines of code to write: 15 lines
  • Estimated time of completion: 15 min
  1. Napisz program, który przeliczy wprowadzoną liczbę rzymską na jej postać dziesiętną.
  2. Napisz drugą funkcję, która dokona procesu odwrotnego.
The whys and wherefores:
 
  • Definiowanie i uruchamianie funkcji
  • Sprawdzanie przypadków brzegowych (niekompatybilne argumenty)
  • Parsowanie argumentów funkcji
  • Definiowanie i korzystanie z dict z wartościami
  • Sprawdzanie czy element istnieje w dict
  • Rzutowanie i konwersja typów