Настављамо са функцијама, које ћете често користити како у Python-у тако и у било ком другом програмском језику.

Функција представља блок кода који се извршава на позив. Њена улога је избегавање дуплирања кода и/или груписања дела кода у логички повезану целину. Дефинишемо је помоћу кључне речи def:

def example_func():
    print('Овај print се налази у функцији!')

Извршавањем овог кода нећемо добити никакав резултат, пошто функција није позвана. Да бисмо позвали функцију користимо њено име уз заграде:

def example_func():
    print('Овај print се налази у функцији!')


example_func()

Испис:

Овај print се налази у функцији!

Ако тренутно не желимо имплементирати функцију, него желимо је само дефинисати, користимо кључну реч pass. Она у Python-у има значење као празан блок у другим програмским језицима, нпр. Java-и или C#-у.

def example_func():
    pass


example_func()

Овај код такође неће имати никакав испис, пошто функција практично није имплементирана, али се неће јавити ни грешка, јер је pass сасвим валидна синтакса.

Повратна вредност функције дефинише се кључном речи return, у супротном повратна вредност је None. То можемо проверити исписом повратне вредности наше функције:

def example_func():
    pass


print(example_func())

Испис:

None

Наравно, боље је да ми сами дефинишемо повратну вредност:

def example_func():
    return 'Ово је враћени стринг из функције'


print(example_func())

Испис:

Ово је враћени стринг из функције

Као што видите, прво се изврши функција example_func() те се њена вредност испише помоћу print() функције.

Функцији можемо проследити и аргументе. Аргументи представљају промењиве које су видљиве унутар функције. У функцији можемо приступити само њима или глобалним промењивим, док не можемо користити промењиве из других функција.

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


print(example_func(1, 2))

Испис:

3

Овде можете видети пример функције која прима два аргумента и враћа њихов збир.

На овај начин ми смо дефинисали функцију која прима две вредности и самим тим увек морамо проследити две вредности. Ако бисмо проследили мање или више програм би пукао и ми бисмо добили грешку.

Ипак, ми можемо подржати да наша функција прима произвољан број аргумента идућом синтаксом:

def example_func(a, b, *args):
    print(f'a је: {a}')
    print(f'b је: {b}')
    print(f'args је: {args}')


example_func(1, 2, 3, 4, 5, 6, 7, 8)

Испис:

a је: 1
b је: 2
args је: (3, 4, 5, 6, 7, 8)

Навели смо два аргумента и *args (звездица је обавезна), а наша функција је примила 8 аргумената. Ово је зато што Python прва два аргумента према позицији додели промењивим a и b, док остале запакује у tuple и смести у *args.

Поред *args механизма, имамо и **kwargs (обратите пажњу на две звездице). kwargs је скраћено од keyword arguments и представља прослеђивање аргумента по паровима кључ-вредност. Погледајмо на примеру:

def example_func(a, b, *args, **kwargs):
    print('-' * 10)
    print('Аргументи')
    print('-' * 10)
    print(f'a је: {a}')
    print(f'b је: {b}')
    print('-' * 10)
    print('args')
    print('-' * 10)
    for index, arg in enumerate(args):  # Пошто је args tuple ми можемо итерирати кроз њега
        print(f'args[{index}] је: {arg}')
    print('-' * 10)
    print('kwargs')
    print('-' * 10)
    for key, value in kwargs.items():  # kwargs можемо посматрати као речник
        print(f'Под кључем {key} прослеђена је вредност {value}')


example_func(1, 2, 3, 4, 5, 6, 7, 8, name='Коста', username='kostakuu')

Испис:

----------
Аргументи
----------
a је: 1
b је: 2
----------
args
----------
args[0] је: 3
args[1] је: 4
args[2] је: 5
args[3] је: 6
args[4] је: 7
args[5] је: 8
----------
kwargs
----------
Под кључем name прослеђена је вредност Коста
Под кључем username прослеђена је вредност kostakuu

Из једне функције можемо позвати другу функцију. Овде видимо да понављамо испис цртица па сам наслов и цртице можемо издвојити у засебну функцију format_title():

def format_title(title):
    print('-' * 10)
    print(title)
    print('-' * 10)


def example_func(a, b, *args, **kwargs):
    format_title('Аргументи')
    print(f'a је: {a}')
    print(f'b је: {b}')
    format_title('args')
    for index, arg in enumerate(args):  # Пошто је args tuple ми можемо итерирати кроз њега
        print(f'args[{index}] је: {arg}')
    format_title('kwargs')
    for key, value in kwargs.items():  # kwargs можемо посматрати као речник
        print(f'Под кључем {key} прослеђена је вредност {value}')


example_func(1, 2, 3, 4, 5, 6, 7, 8, name='Коста', username='kostakuu')

Испис:

----------
Аргументи
----------
a је: 1
b је: 2
----------
args
----------
args[0] је: 3
args[1] је: 4
args[2] је: 5
args[3] је: 6
args[4] је: 7
args[5] је: 8
----------
kwargs
----------
Под кључем name прослеђена је вредност Коста
Под кључем username прослеђена је вредност kostakuu

До сада смо видели позиционе аргументе, јер смо их додавали тако да a одговара првој прослеђеној вредности, b другој итд. Поред њих можемо користити и именоване.

def example_func(a, b):
    print(f'a је: {a}')
    print(f'b је: {b}')


example_func(b=1, a=2)

Испис:

a је: 2
b је: 1

На овај начин. не морамо испоштовати позицију, већ можемо проследити аргументе произвољним редоследом. Ако желимо, можемо учинити да је овај приступ, прослеђивање именованих аргумената, обавезан. На пример, имам један позициони аргумент a и два именована b и c:

def example_func(a, *, b, c):  # Звездица означава да сви аргументи после ње морају бити прослеђени по имену у формату argument_name=value
    print(f'a је: {a}')
    print(f'b је: {b}')
    print(f'c је: {c}')


example_func(1, b=2, c=3)  # Овде можемо видети тај формат за аргументе b и c
# Ако бисмо позвали функцију на следећи начин: example_func(1, 2, c=3)
# Добили бисмо TypeError
# TypeError: example_func() takes 1 positional argument but 2 positional arguments (and 1 keyword-only argument) were given

Испис:

a је: 1
b је: 2
c је: 3

За крај могуће је и аргумент (био он позициони или именовани) учинити опционим. Односно, ако корисник не проследи његову вредност, узима се подразумевана. На следећем примеру наша функција ће имати два обавезна параметра: а (позициони) и c (именовани) те један опциони параметар b (именовани) подразумеване вредности 5:

# Ако b није прослеђено оно добија вредност 5 (подразумевану вредност)
# Самим додавањем подразумевани вредности ми аргумент чини опционим и корисник не мора проследити његову вредност
def example_func(a, *, b=5, c):
    print(f'a је: {a}')
    print(f'b је: {b}')
    print(f'c је: {c}')


example_func(1, c=3)

print('-' * 10)

example_func(1, b=2, c=3)

Испис:

a је: 1
b је: 5
c је: 3
----------
a је: 1
b је: 2
c је: 3

У Python-у постоје и неименоване функције, такозване lambda функције. Оне могу примити произвољан број параметара, али могу имати само један израз унутар себе (формат им је lambda arguments: expression). О њима нећу пуно, али ево једног примера sum функције и sum lambda функције:

def sum(number1, number2):
    return number1 + number2

# Обратите пажњу да се lambda функције могу чувати као промењиве
# Аргументи се наводе после кључне речи lambda одвојени зарезом
# Код који је написан после двотачке се сматра повратном вредношћу функције
# После двотачке се може налазити само један израз
sum_lambda = lambda number1, number2: number1 + number2

print(f'sum функција за бројеве 1 и 2: {sum(1, 2)}')
print(f'sum lambda функција за бројеве 3 и 4: {sum_lambda(3, 4)}')

Испис:

sum функција за бројеве 1 и 2: 3
sum lambda функција за бројеве 3 и 4: 7

Толико за данас. У идућем чланку прелазим на класе, где ћемо упознати још неколико врста функција, али и како руковати са објектима у Python-у.