# Własne funkcje

# Funkcje

Funkcje to "czasowniki" w języku programowania. Czyli to nazwany blok kodu który wykonuje jakieś działania. Czasami w jego wyniku jest również zwracana jakaś wartość.

Do tej pory korzystaliśmy z funkcji dostarczonych nam przez Pythona (np . `print`), lub "wgranych" z biblioteki / modułu.

Pisząc własne programy już na tym etapie zetknęliśmy się z sytuacją gdy robiliśmy podobną rzecz wiele razy - zmieniały się np. tylko dane wejściowe np. modyfikowaliśmy jakiś adres w książce adresowej, gdzie zmieniało się tylko, który adres był modyfikowany.

Możemy taką funkcjonalność ;) zebrać w całość i udostępnić jako własną funkcję. Należy pamiętać, że Python odczytuje nasz kod linijka po linijce, z góry na dół - więc musimy stworzyć nasz "czasownik" przed jego użyciem (deklaracja funkcji musi być wcześniej w kodzie).

Własną funkcję deklarujemy używając słowa **`def`**.

[![](https://wiki.robisz.to/uploads/images/gallery/2024-10/scaled-1680-/image-1728912601706.png)](https://wiki.robisz.to/uploads/images/gallery/2024-10/image-1728912601706.png)

np.

```python
def kwadrat(x:int) ->  int:
	wynik = x * x
	return wynik
```

Zwróćcie uwagę na słowo `return` - wykorzystujemy je jeśli chcemy, żeby nasza funkcja poza wykonaniem jakiejś operacji zwróciła nam jakąś wartość (którą np. możemy przypisać do zmiennej). Bardzo dużo funkcji korzysta z tej opcji - np. funkcja `sum` zwraca nam sumę dwóch liczb, funkcja `max` zwraca nam największą wartość przechowywaną chociażby na liście itd. 

Nie jest to jednak reguła - np. funkcja `print` wyświetla nam daną zawartość na ekranie, ale nie zwraca żadnej wartości.

Powyższy przykład zawiera nieco nieobowiązkowych rzeczy:

- informację o oczekiwanym typie danych parametru wykorzystywanego w funkcji (`x:int`)
- informację o zwracanym typie danych (`-> int`)

Dodawanie tych informacji jest dobrą praktyką - ułatwia nam (i innym użytkownikom tego kodu) korzystanie z programu.

Ponadto dzięki nim narzędzia jakich używamy do pisania będą w stanie podpowiadać nam w przypadku popełnienia błędu związanego z użyciem nieprawidłowego typu.

Tak skonstruowana funkcje wykorzystujemy identycznie jak te wbudowane np.

```python
def kwadrat(x:int) ->  int:
	wynik = x * x
	return wynik

liczba = kwadrat(2)
print(liczba)
```

Powyższa kod wyświetli nam `4` gdyż jest to `2` podniesione do kwadratu (a właśnie to robi ta funkcja kwadrat).

# Parametry pozycyjne

Paremetry do funkcji możemy przekazywać w kolejności ich zadeklarowania w sygnaturze funkcji np.

```python
def wydrukuj_zmienne(a, b, c):
    print("a to:", a)
    print("b to:", b)
    print("c to:", c)

wydrukuj_zmienne(1,2,3)
```

zakończy się wynikiem:

```
a to: 1
b to: 2
c to: 3
```
Czyli do a została przypisana 1, do b 2, a do c 3.

Jeśli przekazujemy parametry w ten sposób musimy znać ich kolejność w sygnaturze funkcji.

# Parametry po kluczu

Możemy też skorzystać z innego wariantu:

```python
def wydrukuj_zmienne(a, b, c):
    print("a to:", a)
    print("b to:", b)
    print("c to:", c)

wydrukuj_zmienne(c=1,a=3,b=2)
```

co da:

```
a to: 3
b to: 2
c to: 1
```

W tym przypadku wywołując funkcję dokładnie podaliśmy do jakiej zmienne powinny przechowywać wskazane wartości.

Oznacza to trochę więcej pisania - ale jest mniejsze ryzyko popełnienia błędu. Ten wariant jest też bardzo przydatny przy bardziej rozbudowanych funkcjach, które mają masę możliwych parametrów - nie musimy zapamiętywać pozycji każdego z nich.

# Zakres (scope)

"Wnętrze" funkcji jest odizolowane od reszty kodu. Ozancza to, że np. zmienna `moja_zmienna` zadaklarowana poza funkcją i identycznie nazwana zmienna wewnątrz funkcji to 2 RÓŻNE zmienne(!).

```python
moja_zmienna = 55 # deklaruje zmienna 

def moja_funkcja():
    moja_zmienna = 1    # deklaruje zmienna wewnatrz funkcji
    print(moja_zmienna)

moja_funkcja()
print(moja_zmienna)

# wynikeim będzie
# 1
# 55
# bo mimo identycznej nazwy
# zmienna wewnątrz funkcji operuje
# w innym zakresie (ma swoje wlasne nazwy)
```