Tworzenie własnych funkcji

Stronę tą wyświetlono już: 228 razy

Funkcje jednoargumentowe lambda

Słowo kluczowe lambda umożliwia utworzenie w danym miejscu kodu funkcji jednoargumetnowej, której kod ogranicza się do jednej linijki. Tego typu funkcje wykorzystuje się wszędzie tam, gdzie ma się pewność jednokrotnego jej użycia. Oto jak można zadeklarować taką funkcję:

Listing 1
  1. import math
  2. f = lambda x: math.sin(x)
  3. print("sin(pi/2) = {f}".format(f = f(math.pi / 2)))

Wynik działania powyższego kodu:

sin(pi/2) = 1.0

Definiowanie funkcji

W Pythonie nie ma możliwości przeciążania funkcji, co spowodowane jest tym, że wszystko, włącznie z funkcjami w Pythonie jest etykietą. Co by się stało, gdybym utworzył jedną funkcję np. przyjmującą jeden argument i drugą o takiej samej nazwie, ale przyjmującą dwa argumenty? Odpowiedź brzmi: pierwsza funkcja zostałaby nadpisana przez drugą. Z tego powodu w Pythonie funkcje definiuje się w dość dziwaczny (jak na mój gust) sposób. Oto prosty pierwszy przykład funkcji:

Listing 2
  1. def silnia(n):
  2. if n < 2:
  3. return 1
  4. return n * silnia(n - 1)

Jak widać na powyższym kodzie funkcji rekurencyjnej o nazwie silnia (która wiadomo co liczy) słowo kluczowe def rozpoczyna definicję funkcji, następnie standardowo jest nazwa funkcji i pomiędzy nawiasami okrągłymi lista jej argumentów, która w tym przypadku ogranicza się do jednego. Co ciekawe Python automatycznie rozszerza zakres danych, dzięki czemu łatwo można wykonać obliczenie np. silnia(100). Zapewniam, że Python policzy to dokładnie.

Rekurencyjne rozwiązanie jest jednak niezalecane (zwłaszcza w przypadku silni), ponieważ za każdym razem komputer musi zapamiętywać poprzedni krok a to znacząco spowalnia pracę. A więc lepiej napisać funkcję silnia za pomocą iteracji:

Listing 3
  1. def silnia(n):
  2. s = 1
  3. if n < 2:
  4. return 1
  5. for i in range(2, n + 1):
  6. s *= i
  7. return s

Nowa wersja funkcji liczącej silnię jest szybsza i umożliwia obliczenie silni np. z 1000 (sprawdźcie, jeżeli nie wierzycie)

Istnieje też możliwość definiowania funkcji, która będzie miała zadeklarowane własne domyślne wartości argumentów. Oto przykład takiej funkcji:

Listing 4
  1. def introduceYourself(name = None, surname = None):
  2. if name is None:
  3. name = input("Proszę, podaj swoje imię: ")
  4. if surname is None:
  5. surname = input("Proszę, podaj swoje nazwisko: ")
  6. print("Witaj {name} {surname}!".format(name = name, surname = surname))
  7. introduceYourself("Zenon", "Pietrucha")
  8. introduceYourself("Zenon")
  9. introduceYourself(surname = "Pietrucha"
  10. introduceYourself()

Pierwsze wywołanie funkcji IntroduceYourself z dwoma argumentami spowoduje wyświetlenie:

Witaj Zenon Pietrucha!

Drugie, z jednym argumentem spowoduje wyświetlenie:

Proszę, podaj swoje nazwisko: Pietrucha
Witaj Zenon Pietrucha!

Trzecie wywołanie funkcji:

Proszę, podaj swoje imię: Zenon
Witaj Zenon Pietrucha!

Czwarte natomiast:

Proszę, podaj swoje imię: Zenon
Proszę, podaj swoje nazwisko: Pietrucha
Witaj Zenon Pietrucha!

Przed listą argumentów, które są opcjonalne można umieścić takie, które są obowiązkowe zawsze. I tu mała uwaga, argumenty opcjonalne muszą być umieszczane zawsze na końcu listy argumentów funkcji.

Istnieje też możliwość utworzenia funkcji, która będzie przyjmowała jeden argument zawierający dane różnego typu. Oto prosty przykład:

Listing 5
  1. def write(varible):
  2. if isinstance(varible, int):
  3. print("Zmienna typu int o wartości równej {v}".format(v = varible))
  4. elif isinstance(varible, str):
  5. print("Zmienna typu str zawierająca tekst \"{s}\"".format(s = varible))
  6. else:
  7. print("Zmienna typu {t}".format(t = type(varible)))
  8. write(10)
  9. write("tekst")
  10. write(10.5)

Efektem działania powyższego kodu będzie:

Zmienna typu int o wartości równej 10
Zmienna typu str zawierająca tekst "tekst"
Zmienna typu float

W powyższym kodzie wykorzystałem dwie dość ciekawe funkcje. Pierwszą z nich jest isinstance, która przyjmuje dwa argumenty: pierwszy to instancja jakiegoś obiektu a drugi to typ obiektu. Funkcja ta zwraca oczywiście True, jeżeli podany obiekt jest instancją podanego typu, False w przeciwnym przypadku.

Druga funkcja to type, zwraca ona tekst, zawierający informacje o typie obiektu.

Istnieje również możliwość utworzenia funkcji, która będzie przyjmowała dowolną liczbę argumentów. Oto przykład:

Listing 6
  1. def introduceYourself(name = None, surname = None, *arg, **kwargs):
  2. if name is None:
  3. name = input("Proszę, podaj swoje imię: ")
  4. if surname is None:
  5. surname = input("Proszę, podaj swoje nazwisko: ")
  6. print("Witaj {name} {surname}!".format(name = name, surname = surname))
  7. for i in arg:
  8. print(i)
  9. for i, desc in kwargs.items():
  10. print(i, desc)
  11. introduceYourself("Zenon", "Pietrucha", "Zajmuję się budowlanką", "Lubię demolować!", specialization = "Demolka!")

Powyższy kod wyświetli:

Witaj Zenon Pietrucha!
Zajmuję się budowalanką
Lubię demolować
specialization Demolka!

Przerywanie działania funkcji można wykonać na dwa sposoby, pierwszy z użyciem słowa kluczowego pass:

Listing 7
  1. def write(varible):
  2. if isinstance(varible, int):
  3. print("Zmienna typu int o wartości równej {v}".format(v = varible))
  4. elif isinstance(varible, str):
  5. print("Zmienna typu str zawierająca tekst \"{s}\"".format(s = varible))
  6. else:
  7. pass

Drugi sposób to zwrócenie wartości None:

Listing 8
  1. def silnia(n):
  2. if n < 0:
  3. return None
  4. s = 1
  5. if n < 2:
  6. return 1
  7. for i in range(2, n + 1):
  8. s *= i
  9. return s

Dokumentacja funkcji

Istnieje możliwość tworzenia własnej dokumentacji tworzonych funkcji, która zostanie wyświetlona w ipythonie, gdy po nazwie funkcji zostanie wpisany znak zapytania. Dokumentacje tworzy się poprzez umieszczenie wieloliniowego komentarza zaraz po nagłówku funkcji w następujący sposób:

Listing 9
  1. def silnia(n):
  2. '''
  3. Funkcja obliczająca silnię z zadanej liczby całkowitej.
  4. '''
  5. if n < 0:
  6. return None
  7. s = 1
  8. if n < 2:
  9. return 1
  10. for i in range(2, n + 1):
  11. s *= i
  12. return s

Wpisanie w ipythonie następującego tekstu:

silnia?

Spowoduje wyświetlenie następującego tekstu:

Signature: silnia(n)
Docstring: Funkcja obliczająca silnię z zadanej liczby całkowitej.
File:      c:userskrzysiek
Type:      function

Pod Linuksem będzie to wyglądało nieco inaczej, aczkolwiek zasada jest taka sama.

Komentarze