# setup
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
Funkcja to wydzielony, zorganizowany fragment kodu przeznaczony do wielokrotnego użycia, któremu nadano nazwę. Funkcje wprowadzają do aplikacji większą modułowość (kod podzielony jest na fragmenty przeznaczone do wykonania jakiegoś zadania) oraz zwiększają stopień ponownego użycia kodu. Funkcje mogą składać się z pojedyńczego wyrażenia lub też z sekwencji wyrażeń, które mają być po sobie wykonane.
W ramach języka Python można wyróżnić kilka grup funkcji:
Dodatkowo, jak każdy język programowania, daje możliwość tworzenia własnych funkcji. W tej części zajmiemy przede wszystkim własnymi funkcjami. Stosowanie funkcji wbudowanych zostało wspomniane w poprzednich częściach kursu natomiast bibliotece standardowej zostanie poświęcony osobny moduł.
Definicja funkcji składa się z nagłówka funkcji - nazwy, argumentów oraz ciała funkcji - sekwencji wyrażeń jakie mają w ramach funkcji być wykonane. Po zdefiniowaniu funkcji, wystarczy, że wywołamy funkcję podając jej nazwę oraz wymagane argumenty.
Ogólna składnia funkcji to:
def nazwa_funkcji(argument1, argument2=0, `[arguments]`):
'''opis funkcji (docstring)
Keyword arguments:
argument1 -- parameter string (requited)
argument2 -- wartość float (optional) -- (default 0.0)
'''
#ciało funkcji
blok instrukcji do wykonania
return <wyrazenie>
nagłówek funkcji - zawiera:
Kolejne linie muszą zaczynać się od wcięcia. Tak jak w przypadku instrukcji warunkowych oraz pętli stosujemy 4 spacje jako wcięcie.
Druga linia (opcjonalna) zawiera opis funkcji. Choć nie jest to wymagane (tj. bez tej części funkcja zadziała), każda funkcja powinna być dobrze udokumentowana. Opis funkcji musi być zawarty pomiędzy trzema apostrofami, tzw. Triple quote.
Trzecia i kolejne linie to ciało funkcji zawierają blok instrukcji, który ma zostać wykonany w ramach funkcji (tzw. ciało funkcji, ang. function body).
return
Nie można zdefiniować w jednym module/skrypcie dwóch funkcji o tej samej nazwie. Jeśli tak zrobimy, druga funkcja nadpisze pierwszą.
Nazewnictwo funkcji powinno być spójne – preferuje się słowa rozdzielone podkreślnikiem, np. moja_funkcja.
Jako przykład zdefiniujmy funkcję obliczającą pole prostokąta. Wynik funkcji można też przypisać do zmiennej. W podstawowej wersji pythona nie określamy typów argumentów ani typu zwracanego wyniku.
def pole_prostakata(bok_a, bok_b):
'''
Funkcja wylicza pole prostokata na podstawie podanego boku a oraz boku b
Keyword arguments:
bok_a float -- bok krótszy (requited)
bok_b float -- bok dłuższy (requited)
'''
pole = bok_a * bok_b
return pole
print(pole_prostakata(5,4))
Funckja wbudowana help()
może być także stosowana z funkcjami zdefiniowanymi przez użytkownika. Wywołując help() z nazwą funkcji jako argumentem, poznamy argumenty funkcji oraz informację zapisaną w docstring.
help(pole_prostakata)
W ramach funkcji można definiować dowolną liczbę argumentów. Sposób definiowania argumentów dzieli się na cztery grupy:
*args
- dowolnej długości lista nie nazwanych argumentów**kvargs
- dowolnej długości lista nazwanych argumentów, ale nie zdefiniowanych w funkcji, muszą się znajdować za argumentami opcjonalnymi* args
stosujemy w sytuacji, gdy do funkcji chcemy przekazać niekoreśloną listę argumentów tego samego typu, natomiast **kvargs
jeżeli chcemy przekazać nieokreśloną listę argumentów o znanej nazwie, z których jedynie nieliczne będą wykorzystane. Stosuje się w wypadku definiowania listy pól w tabeli albo do przekazywania argumentów do innych funkcji wywołwywanych wewnątrz funkcji.
Jeżeli podajemy argumenty zgodnie z kolejnością ich definiowania w nagłówku nazwy argumentów można pominąć, natomiast jeżeli zmieniamy ich kolejność lub nie podajemy wszystkich opcjonalnych, należy podawać ich nazwy. Nazwy należy podawać jeżeli stosujemy **kvargs
.
def pozycyjne(A,B):
return A+B
def opcjonalne(A,B=1.0):
return A/B
pozycyjne(3,4)
opcjonalne(5)
opcjonalne(B=2.,A=4) # zmiana kolejności
lista argumentów i słownik argumentów to zagadnienie nieco bardziej skomplikowane. Najlepiej omówić je na przykładzie.
Listę argumentów stosuje się jeżeli chcemy przekazać do funkcji nieznaną przed wykonaieniem listę argumentów o nieokreślonej liczbie. W praktyce lista argumentów przekazywana jest jako krotka a nie lista. Klasycznym przykładem będzie tu opracowana funkcja suma(), która ma na celu obliczyć sumę wprowadzonych liczb:
def suma(*A):
wynik = 0;
for a in A:
wynik +=a
return wynik
suma(1,2,4,5,6,7)
suma(1)
Co zrobić jeżeli do takiej funkcji chcemy przekazać istniejącą już listę? W takiej sytucji należy zastosować operator *
określony jako operator rozwijania listy/krotki (ang. expand tuple). Zamienia on listę jako w zbiór niezależnych literałów. Jeżeli lista zostanie przekazana bez gwiazdki, zostanie zgłoszony błąd.
lista = [1,2,3,4,5,6,7]
suma(*lista)
W przypadku rozwijanego słownika, każdy utworzony argument funkcji będzie pozycją słownika o kluczu zdefiniowanym przez argument. Dostęp do wartości uzyskamy przez wywołanie słownika z odpowiednim kluczem. Jeżeli funkcja będzie zawierać odwołania do słownika z kluczem, który nie został przekazany fukcja zgłosi błąd.
def slownik(A,**B): #2
return A + B['c'] +B['d'] # funkcja zna zmienne o tej nazwie
slownik(1,c=5,d=2)
Z tego powodu rozwijalne słowniki należy stosować w sytuacji przekazywania atrybutów, dla których zostały zdefiniowane wartości domyślne. W praktyce to rozwiązanie stosuje się, gdy nasza funkcja wywołuje inną funkcję, dla której możemy (ale nie musimy) zmienić domyślne argumenty. Należy się jednak upewnić, czy takie argumenty przekazano.
W języku python każda zmienna raz zainicjownana funkcjonuje do mementu aż zakończy się blok, w ramach którego została zainicjowana lub zostanie ręcznie usunięta operatorem del.
W przypadku zmiennych inicjowanych w głównym ciele skryptu ale też w obrębie pętli i warunków zmienna istnieje aż do zakończenia działania skryptu, natomiast zmienne inicjowane w ciele funkcji tylko do momentu zakończenia działania tej funkcji. Co więcej zmienna inicjowna w obrębie fukcji może mieć taką samą nazwę jak zmienna zainicjowana poza funckcją
a = 3
print(a) #3
def funkcja(b):
print(b) #5
#print a zgłosi błąd, zmienna niezainicjowana
a = 6
print(a) #6
funkcja(5)
print(a) #ponownie 3
Zasięg zmiennych nie dotyczy obiektów złożonych. Jeżeli do funkcji zostanie przekazany obiekt złożony, modyfikowalny (lista, słownik) i w obrębie funkcji zostanie on zmodyfikowany, to zostanie zmodyfikowany również poza funkcją. Nazywa się to przekazywaniem argumentów przez referencję:
lista = [1,2,3,4]
lista
def modyfikuj(lista):
lista.append(10)
modyfikuj(lista)
lista