Funkcije su jedan od najvažnijih koncepata u programiranju i Python ne čini izuzetak. Ako ste ikada kopirali isti blok koda više puta u svom programu, onda definitivno trebate funkcije! U ovom opsežnom vodiču, naučićemo sve što treba da znate o funkcijama u Python-u – od osnovnih koncepata do naprednih tehnika.

Šta su funkcije i zašto su važne?
Funkcija je ponovo iskoristivi blok koda koji izvršava određeni zadatak. Umesto da pišete isti kod iznova kad god vam zatreba, možete ga “upakovati” u funkciju i pozvati je kad god bude potrebno. Ovo vam štedi vreme, čini kod čitljivijim i olakšava održavanje.
Zamislite da pravite sandwich. Umesto da svaki put opisujete sve korake (uzmi hleb, namazi majonez, stavi šunku…), možete jednostavno reći “napravi sendvič”. To je upravo ono što rade funkcije u programiranju!
Osnovni koncept funkcija
Definisanje funkcije u python-u
U Python-u, funkcije se definišu pomoću ključne reči def
praćene nazivom funkcije i zagradama:
def pozdrav():
print("Zdravo, dobrodošli u svet Python funkcija!")
# Pozivanje funkcije
pozdrav() # Output: Zdravo, dobrodošli u svet Python funkcija!
Pozivaju se kucanjem naziva funcije i zadradama, ako funkcija ima parametre, parametri se ubacuju između zagrada.
Funkcije sa parametrima
Parametri omogućavaju funkcijama da primaju podatke i rade sa njima:
def pozdrav_sa_imenom(ime):
print(f"Zdravo, {ime}! Dobrodošli u Python.")
pozdrav_sa_imenom("Ana") # Output: Zdravo, Ana! Dobrodošli u Python.
pozdrav_sa_imenom("Marko") # Output: Zdravo, Marko! Dobrodošli u Python.
u ovom primeru funkcija pozdrav_sa_imenom ima jedan parametar sa nazivom “ime”.
Pri pozivu funcije se prosledjuje vrednost parametra. U ovom slučaju vrednosti su “Ana” i “Marko”
Funkcije u Python-u sa više parametara
def predstavi_se(ime, prezime, godine):
print(f"Ja sam {ime} {prezime} i imam {godine} godina.")
predstavi_se("Marko", "Petrović", 25)
# Output: Ja sam Marko Petrović i imam 25 godina.
Funkcije takodje mogu prihvatati više parametara. unose se parametri razdvojeni zarezom.
Kod poziva se takođe razdvajaju zarezom.
Podrazumevane vrednosti parametara
Možete navediti podrazumevane vrednosti za parametre:
def pozdrav_sa_vremenom(ime, vreme_dana="dan"):
print(f"Dobro {vreme_dana}, {ime}!")
pozdrav_sa_vremenom("Ana") # Output: Dobro dan, Ana!
pozdrav_sa_vremenom("Marko", "jutro") # Output: Dobro jutro, Marko!
pozdrav_sa_vremenom("Jelena", "veče") # Output: Dobro veče, Jelena!
Parametrima je moguće definisati podrazumevanu vrednost , kao na primer vreme_dana="dan"
.
Ako se kao u ovom primeru pozdrav_sa_vremenom("Ana")
prosledi jedan parametar, drugi će imati podrazumevanu vrednost.Ako se prosledi parametar koji ima podrazumevanu vrednost , paramametar će imati vrednost koja je prosleđena kao u primeru pozdrav_sa_vremenom("Marko", "jutro")
, parametar vreme_dana će imati vrednost jutro.
Vraćanje vrednosti
Funkcije mogu da vraćaju vrednosti koristeći ključnu reč return
:
def saberi(a, b):
return a + b
rezultat = saberi(5, 3)
print(rezultat) # Output: 8
# Korišćenje vraćene vrednosti direktno
print(saberi(10, 15)) # Output: 25
Sa reči return možemo vratiti vrednost iz funkcije u glavni program.
Vraćanje više vrednosti
def aritmeticki_operatori(a, b):
return a + b, a - b, a * b, a / b
zbir, razlika, proizvod, kolicnik = aritmeticki_operatori(10, 5)
print(f"Zbir: {zbir}, Razlika: {razlika}, Proizvod: {proizvod}, Količnik: {kolicnik}")
# Output: Zbir: 15, Razlika: 5, Proizvod: 50, Količnik: 2.0
Tipovi argumenata funkcija
Pozicioni argumenti
def opisi_ljubimca(ime, vrsta):
print(f"Imam {vrsta}a i zove se {ime}.")
opisi_ljubimca("Rex", "pas") # Output: Imam pasa i zove se Rex.
opisi_ljubimca("Garfield", "mačka") # Output: Imam mačku i zove se Garfield.
Parametri funkcije dobijaju vrednosti resosledom kojim su prosledjeni ako se u pozivu ne nazanači koja vrednost je za koji parametar.
Imenujući argumente
# Možete koristiti iste argumente iz prethodnog primera na drugi način
opisi_ljubimca(ime="Fluffy", vrsta="zec")
opisi_ljubimca(vrsta="papagaj", ime="Alberto") # Redosled nije važan
Ako u pozivu imenejumo koji argument dobija koju vrednost, onda redosled navođenja nije bitan nego argumenti dobijajau vrednost po nazivu.
Kombinacija pozicionih i imenovanih argumenata
def napravi_profil(ime, email, godine=None, grad=None):
profil = f"{ime} ({email})"
if godine:
profil += f", {godine} godina"
if grad:
profil += f", iz {grad}a"
return profil
print(napravi_profil("Ana", "ana@email.com"))
# Output: Ana (ana@email.com)
print(napravi_profil("Marko", "marko@email.com", godine=30))
# Output: Marko (marko@email.com), 30 godina
print(napravi_profil("Jelena", "jelena@email.com", grad="Beograd", godine=25))
# Output: Jelena (jelena@email.com), 25 godina, iz Beograda
# Greška: pozicioni argument ne može nakon imenovanog
# print(napravi_profil("Petar", email="petar@email.com", 28)) # Ne radi!
U pozivu funkcije moguće je kombinovati prosleđivanje vrednosti po poziji redosledom navođenja, i imenovanjem parametara
Varijabilni broj argumenata
*args – Proizvoljan broj pozicionih argumenata
def saberi_sve(*brojevi):
ukupno = 0
for broj in brojevi:
ukupno += broj
return ukupno
print(saberi_sve(1, 2, 3)) # Output: 6
print(saberi_sve(10, 20, 30, 40, 50)) # Output: 150
print(saberi_sve()) # Output: 0
# Možete koristiti i funkciju sum() za istu svrhu
def saberi_sve_v2(*brojevi):
return sum(brojevi)
**kwargs – Proizvoljan broj imenovanih argumenata
def kreiraj_korisnika(**podaci):
for kljuc, vrednost in podaci.items():
print(f"{kljuc}: {vrednost}")
kreiraj_korisnika(ime="Marko", prezime="Petrović", grad="Novi Sad")
# Output:
# ime: Marko
# prezime: Petrović
# grad: Novi Sad
kreiraj_korisnika(user_id=12345, email="marko@email.com", aktivan=True)
# Output:
# user_id: 12345
# email: marko@email.com
# aktivan: True
Kombinacija args i kwargs
def fleksibilna_funkcija(obavezni_arg, *args, **kwargs):
print(f"Obavezni argument: {obavezni_arg}")
print(f"Dodatni pozicioni argumenti: {args}")
print(f"Dodatni imenovani argumenti: {kwargs}")
fleksibilna_funkcija("test", 1, 2, 3, ime="Ana", godine=25)
# Output:
# Obavezni argument: test
# Dodatni pozicioni argumenti: (1, 2, 3)
# Dodatni imenovani argumenti: {'ime': 'Ana', 'godine': 25}
Opseg promenljivih (Scope)
Lokalne promenljive
def moja_funkcija():
lokalna_promenljiva = "Ja postojim samo unutar funkcije"
print(lokalna_promenljiva)
moja_funkcija() # Output: Ja postojim samo unutar funkcije
# Greška: lokalna_promenljiva nije definisana van funkcije
# print(lokalna_promenljiva) # NameError
Promenjive definisane u funkciji su lokalne za tu funkciju i ne postoje izvan funkcije i ne mogu se koristiti van funkcije.
Globalne promenljive
globalna_promenljiva = "Ja sam dostupna svugde"
def prikazi_globalnu():
print(globalna_promenljiva)
prikazi_globalnu() # Output: Ja sam dostupna svugde
# Može se pristupiti direktno
print(globalna_promenljiva) # Output: Ja sam dostupna svugde
Promenjive koje su definisane u glavnom programu se mogu koristiti i u funkcijama.
Menjanje globalne promenljive u funkciji
brojac = 0
def povecaj_brojac():
global brojac
brojac += 1
print(f"Brojač: {brojac}")
povecaj_brojac() # Output: Brojač: 1
povecaj_brojac() # Output: Brojač: 2
print(brojac) # Output: 2
Takođe je moguće promeniti vrednost globalne promenjive u funkciji.
Ugneždene funkcije
def spoljna_funkcija(x):
def unutrasnja_funkcija(y):
return x + y
return unutrasnja_funkcija
dodaj_pet = spoljna_funkcija(5)
print(dodaj_pet(10)) # Output: 15
print(dodaj_pet(20)) # Output: 25
# Ili direktno
print(spoljna_funkcija(3)(7)) # Output: 10
Lambda funkcije
Lambda funkcije su anonimne funkcije koje se koriste za jednostavne operacije:
# Obična funkcija
def kvadrat(x):
return x ** 2
# Lambda funkcija
kvadrat_lambda = lambda x: x ** 2
print(kvadrat(5)) # Output: 25
print(kvadrat_lambda(5)) # Output: 25
# Lambda sa više argumenata
saberi = lambda x, y: x + y
print(saberi(3, 7)) # Output: 10
# Lambda u sorted funkciji
studenti = [("Ana", 95), ("Marko", 85), ("Jelena", 90)]
sortirani_po_oceni = sorted(studenti, key=lambda student: student[1], reverse=True)
print(sortirani_po_oceni)
# Output: [('Ana', 95), ('Jelena', 90), ('Marko', 85)]
Rekurzija
Rekurzija je kada funkcija poziva samu sebe:
def faktorijel(n):
if n <= 1:
return 1
else:
return n * faktorijel(n - 1)
print(faktorijel(5)) # Output: 120 (5 * 4 * 3 * 2 * 1)
# Fibonačijev niz
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
for i in range(8):
print(fibonacci(i), end=" ") # Output: 0 1 1 2 3 5 8 13
Dokumentiranje funkcija
Docstrings
def izracunaj_krug(poluprecnik):
"""Izračunava površinu i obim kruga.
Args:
poluprecnik (float): Poluprečnik kruga.
Returns:
tuple: (površina, obim)
Primer:
>>> izracunaj_krug(5)
(78.53981633974483, 31.41592653589793)
"""
from math import pi
povrsina = pi * poluprecnik ** 2
obim = 2 * pi * poluprecnik
return povrsina, obim
# Pristupanje docstring-u
print(izracunaj_krug.__doc__)
Dekoratori
Dekoratori omogućavaju modifikaciju funkcija:
import time
def merenje_vremena(funkcija):
def wrapper(*args, **kwargs):
pocetak = time.time()
rezultat = funkcija(*args, **kwargs)
kraj = time.time()
print(f"{funkcija.__name__} je izvršena za {kraj - pocetak:.2f} sekundi")
return rezultat
return wrapper
@merenje_vremena
def spora_funkcija():
time.sleep(2)
return "Završeno!"
rezultat = spora_funkcija()
# Output: spora_funkcija je izvršena za 2.00 sekundi
print(rezultat) # Output: Završeno!
Praktični primeri
1. Kalkulator
def kalkulator():
print("=== Jednostavni kalkulator ===")
print("1. Sabiranje (+)")
print("2. Oduzimanje (-)")
print("3. Množenje (*)")
print("4. Deljenje (/)")
print("5. Stepenovanje (**)")
print("6. Izlaz")
while True:
izbor = input("\nIzaberite operaciju (1-6): ")
if izbor == '6':
print("Dovidjenja!")
break
if izbor in ['1', '2', '3', '4', '5']:
try:
broj1 = float(input("Unesite prvi broj: "))
broj2 = float(input("Unesite drugi broj: "))
if izbor == '1':
rezultat = broj1 + broj2
print(f"Rezultat: {broj1} + {broj2} = {rezultat}")
elif izbor == '2':
rezultat = broj1 - broj2
print(f"Rezultat: {broj1} - {broj2} = {rezultat}")
elif izbor == '3':
rezultat = broj1 * broj2
print(f"Rezultat: {broj1} * {broj2} = {rezultat}")
elif izbor == '4':
if broj2 != 0:
rezultat = broj1 / broj2
print(f"Rezultat: {broj1} / {broj2} = {rezultat}")
else:
print("Greška: Deljenje nulom nije moguće!")
elif izbor == '5':
rezultat = broj1 ** broj2
print(f"Rezultat: {broj1} ** {broj2} = {rezultat}")
except ValueError:
print("Greška: Molimo unesite validne brojeve!")
else:
print("Neispravan izbor!")
# Pokretanje kalkulatora
kalkulator()
2. Upravljanje bankovnim računom
class BankovniRacun:
def __init__(self, vlasnik, stanje=0):
self.vlasnik = vlasnik
self._stanje = stanje
self._transakcije = []
def polozi_novac(self, iznos):
if iznos > 0:
self._stanje += iznos
self._transakcije.append(f"Depozit: +{iznos} RSD")
print(f"Uspešno ste položili {iznos} RSD. Novo stanje: {self._stanje} RSD")
else:
print("Greška: Iznos mora biti pozitivan!")
def podizanje_novca(self, iznos):
if 0 < iznos <= self._stanje:
self._stanje -= iznos
self._transakcije.append(f"Isplata: -{iznos} RSD")
print(f"Uspešno ste podigli {iznos} RSD. Novo stanje: {self._stanje} RSD")
elif iznos > self._stanje:
print("Greška: Nedovoljno sredstava!")
else:
print("Greška: Iznos mora biti pozitivan!")
def stanje_na_racunu(self):
print(f"Trenutno stanje na računu: {self._stanje} RSD")
return self._stanje
def istorija_transakcija(self):
print(f"\n=== Istorija transakcija za {self.vlasnik} ===")
if not self._transakcije:
print("Nema transakcija.")
else:
for i, transakcija in enumerate(self._transakcije, 1):
print(f"{i}. {transakcija}")
print(f"Trenutno stanje: {self._stanje} RSD")
# Korišćenje
racun = BankovniRacun("Marko Petrović", 1000)
racun.polozi_novac(500)
racun.podizanje_novca(300)
racun.stanje_na_racunu()
racun.istorija_transakcija()
3. Analiza teksta
def analiziraj_tekst(tekst):
"""Analizira osnovne karakteristike datog teksta."""
# Uklanjanja znakova interpunkcije
import string
# Osnovna statistika
broj_karaktera = len(tekst)
broj_razmaka = tekst.count(' ')
broj_reci = len(tekst.split())
# Analiza rečenica
broj_recenica = tekst.count('.') + tekst.count('!') + tekst.count('?')
# Najčešće reči
reci = tekst.lower().translate(str.maketrans('', '', string.punctuation)).split()
recnik_reci = {}
for rec in reci:
if rec in recnik_reci:
recnik_reci[rec] += 1
else:
recnik_reci[rec] = 1
# Sortiranje po frekvenciji
najcesece_reci = sorted(recnik_reci.items(), key=lambda x: x[1], reverse=True)[:5]
print("=== Analiza teksta ===")
print(f"Ukupno karaktera: {broj_karaktera}")
print(f"Ukupno reči: {broj_reci}")
print(f"Prosečna dužina reči: {broj_karaktera/broj_reci:.2f} karaktera" if broj_reci > 0 else "N/A")
print(f"Broj rečenica: {broj_recenica}")
print(f"Prosečno reči po rečenici: {broj_reci/broj_recenica:.2f}" if broj_recenica > 0 else "N/A")
print("\nNajčešće reči:")
for i, (rec, broj) in enumerate(najcesece_reci, 1):
print(f"{i}. '{rec}': {broj} puta")
# Primer korišćenja
tekst = """Python je programski jezik opšte namene koji je poznat po svojim jednostavnoj sintaksi.
Python se koristi u web razvoju, naučnim istraživanjima i veštačkoj inteligenciji.
Učenje Python-a je odlična investicija u vašu programersku karijeru."""
analiziraj_tekst(tekst)
Best Practices – Najbolje prakse za funkcije
1. Jednu stvar dobro
Funkcija treba da radi jednu stvar i da to radi dobro. Ako funkcija ima više od jedne odgovornosti, razdvojite je na više manjih funkcija.
# Loše - funkcija radi previše stvari
def obradi_korisnike(korisnici, fajl):
# Validacija
if not korisnici:
return
# Sortiranje
korisnici.sort(key=lambda x: x['ime'])
# Formatiranje
formatirani = [f"{k['ime']} - {k['email']}" for k in korisnici]
# Pisanje u fajl
with open(fajl, 'w') as f:
f.write('\n'.join(formatirani))
# Dobro - svaka funkcija ima jednu odgovornost
def validiraj_korisnike(korisnici):
return korisnici if korisnici else []
def sortiraj_korisnike(korisnici):
return sorted(korisnici, key=lambda x: x['ime'])
def formatiraj_korisnike(korisnici):
return [f"{k['ime']} - {k['email']}" for k in korisnici]
def zapisi_u_fajl(podaci, fajl):
with open(fajl, 'w') as f:
f.write('\n'.join(podaci))
# Korišćenje
korisnici = validiraj_korisnike(korisnici)
korisnici = sortiraj_korisnike(korisnici)
formatirani = formatiraj_korisnike(korisnici)
zapisi_u_fajl(formatirani, fajl)
2. Deskriptivni nazivi
Nazivi funkcija treba da opisuju šta funkcija radi:
# Loše nazive
def f(x, y):
return x + y
def pr(s):
print(s)
# Dobri nazivi
def saberi_brojeve(prvi_broj, drugi_broj):
return prvi_broj + drugi_broj
def ispisi_poruku(poruka):
print(poruka)
3. Izbegavajte previše parametara
Ako funkcija ima više od 3-4 parametra, razmislite o korišćenju rečnika ili klase:
# Loše - previše parametara
def kreiraj_korisnika(ime, prezime, email, telefon, adresa, grad, zip_kod):
# ...
# Dobro - korišćenje rečnika
def kreiraj_korisnika(podaci_korisnika):
ime = podaci_korisnika.get('ime')
prezime = podaci_korisnika.get('prezime')
# ...
# Još bolje - korišćenje klase
class KorisnikPodaci:
def __init__(self, ime, prezime, email, telefon=None, adresa=None):
self.ime = ime
self.prezime = prezime
self.email = email
self.telefon = telefon
self.adresa = adresa
def kreiraj_korisnika(korisnik):
# ...
4. Vraćajte konzistentne tipove podataka
Funkcija treba uvek da vraća isti tip podataka:
python# Loše - vraća različite tipove
def pronadji_korisnika(korisnici, id):
for korisnik in korisnici:
if korisnik['id'] == id:
return korisnik
return None # Ili False, ili -1...
# Dobro - uvek vraća isti tip
def pronadji_korisnika(korisnici, id):
for korisnik in korisnici:
if korisnik['id'] == id:
return korisnik
return {} # Ili None, ali konzistentno
Više o funkcijama na W3C
Predhodna lekcija – python sintaksa za početnike
Sledeća lekacija – klase u python-u