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'),
        {'Jan 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ą ciągi znaków

def clean(text: str) -> str:
    """
    >>> clean('  bolesława chrobrego ')
    'Bolesława Chrobrego'
    >>> clean('ul Jana III SobIESkiego')
    'Jana III Sobieskiego'
    >>> clean('\tul. Jana trzeciego Sobieskiego')
    'Jana III Sobieskiego'
    >>> clean('ulicaJana III Sobieskiego')
    'Jana III Sobieskiego'
    >>> clean('UL. JA\tNA 3 SOBIES\tKIEGO')
    'Jana III Sobieskiego'
    >>> clean('UL. Zygmunta III WaZY')
    'Zygmunta III WaZY'
    >>> clean('ULICA JANA III SOBIESKIEGO  ')
    'Jana III Sobieskiego'
    >>> clean('ULICA. JANA III SOBIeskieGO')
    'Jana III Sobieskiego'
    >>> clean(' Jana 3 Sobieskiego  ')
    'Jana III Sobieskiego'
    >>> clean('Jana III Sobi\teskiego ')
    'Jana III Sobieskiego'
    >>> clean('ul.Mieszka II')
    'Mieszka II'
    """
    return text
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

Table 1.6. 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: float) -> str:
    """
    >>> 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 number
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: float) -> str:
    """
    >>> 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 number
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