Bevezetés a Python nyelvbe#
Python egy álatlános célú, magas színtű, gyengén típusos, interpretált programozási nyelv. Nézzük meg egyesével, mit jelentenek ezek a jelzők.
Általános célú, így számos különböző célra használható a web applikációktól kezdve, tudományos kutatáson át, különböző szkript feladatok elátására.
A nyelv magas színtű, mivel a Python magas szintű absztrakciót nyújt a gépi kódhoz képest. Ezzel szemben a Matlab főleg mérnöki és kutatási feladatokra használható jól.
Gyengén típusos, mivel nem szükséges előre definiálni az egyes változók típusát, így a változó deklarálás és inicializálása nem válik tisztán szét. A változók típusa futás időben, dinamikusan döl el.
Interpretált, ugyanis a Python kód önmagában nem futtatható, szükséges hozzá egy interpreter, ezért általánosságban elmondható, hogy a Python kód lassabban fut, mint egy olyan nyelv kódja, mely gépi kódra fordul (pl. C vagy C++).
Kiegészítő anyag
Megjegyezzük azonban, hogy nem minden esetben érzékelhető a Python nyelv lassúsága. Bizonyos esetekben azt tapasztalhatjuk, hogy a Python kód gyorsabban
fut mint egy álatlunk írt C kód. Ez azért lehetséges, mert számos Python könyvtár mögött direketen alacsonyabb szintű nyelven írt kódok futnak, amikor bizonyos műveleteket,
függvényeket hívunk; ilyen például különboző mátrix műveletek a numpy
könyvtárban. Nagy méretű mátrix szorzás Pythonban nagy valószínűséggel gyorsabban fog futni, mintha mi probálnánk azt C nyelvbe megírni valamilyen könyvtár használata nélkül. Továbbá, érdemes tudni, hogy a Python képes arra, hogy futás időben lefordítsa a Python kódot gépi kódra (Just-In-Time fordítás), de annak futás ideje és memória kezelése még mindig elmaradhat egy alacsony nyelv implementációjától.
A Python programozási nyelvet egy holland programozó Guido van Rossum alkotta meg az 1990-es évek elején. A nyelvnek két nagy verziója van. A Python 2, a régebbi, amellyel még találkozhatunk elvétve. Python 3-t 2008-ban mutatták be. A Python 3 nem kompatibilis a 2-es verzióval, így fontos tisztában lennünk a két verzió közötti különbségekkel. Jelenleg a 3.8-as verzó a legfrissebb, melyet 2023-ban adtak ki. Habár a nyelv története 3 évtizedre nyúlik vissza, népszerűsége az elmúlt 5-10 évben kezdett emelkdeni. Mára a Python az egyik legkedveltebb és a munkaerő piacon at egyik legkeresetebb nyelvek közé tartozik. A mesterséges intelligencia, mélytanulási algoritmusok és adat tudományok elsődleges nyelve. Könnyű portolhatósága miatt számos felhasználó programba beépült, és ezek a programok Python nyelven nyújtanak hozzáférést a programozási felületükhöz, vagy szak zsargonban API-juk (Application Programming Interface) hoz, így péládul QGIS. Gyakran találkozhatunk a Pythonnal szervereken, ahol különböző backend logikát valósít meg.
Kezedtbe a nyelvet úgy tervezték, hogy kezdők is gyorsan el tudják sajátítani, illetve kikényszerítsen helyes kódolási technikát (lásd identálás). Későbbiekben fontos szempont volt a nyelv egyszerűsége, és hogy a programozó az eredményre tudjon koncentrálni, és ne a nyelv különböző elemeire keljen fókuszálni; így a nyelv különösen alkalmas ötletek kipróbálására, prototipizálásra. A számos, sok funkciójú, jó minőségű és nyílt (ingyenesen elérhető) programcsomagok további érvet nyújt ahhoz, hogy ezt a programnyelvet válasszuk. Ki szeretném hagsúlyozni, a legtöbb csomag ingyenességét: felhasználói, és sok esetben kereskedelmi célra is elérhetőek ezek, beleértve a legtöbb Python ekoszisztémába tartozó fejlesztői eszközt.
Kiegészítő anyag
Nyílt forráskód (open source), tehát hogy bele tudok nézni a forrás kódba, nem feltétlenül jelenti a program teljes körű ingyenességét. Nyílt és ingyenesség kérdése két különböző definíció, habár nyílt forráskódú programok gyakran bizonyos szempontból ingyenesek. “Ingyenességnek” is lehetnek különböző fokozatai: ingyenes a felhasználása kereskedelmi célra, vagy csak nem kereskedelmi (pl. akadémiai, hobbi) célú használata engedélyezett, engedélyezett-e a terjesztése, beépíthető-e a könyvtár kereskedelmi termékékbe és ha igen azt jeleznünk kell-e. Ezek miatt számos licensz kvázi szabvány létezik, melyek pl. MIT, BSD, LGPL, GPL, FOSS. Mindig bizonyosodjunk meg arról, hogy a könyvtárakat, eszközöket licenszének megfelelően használjuk. Mindazonáltal érdemes megjegyezni, hogy a mérnöki szoftverekkel ellentétben, az IT iparban, számos a közösség által fejlesztet eszököz, melyek rendkívűl megengedő licenszeléssel vannak kiadva, napi szinten vannak használva.
A Python, mivel interpretált nyelv, ezért szükséges a Pyton futtató környezet telepítése az operációs rendszerünkre; ez online letölthető. Maga az interpreter egy konzol alkalmazás; a forráskódot egy ASCII szöveg szerkesztőben írjuk, és a kódot konzolon kersztül adjuk át a Python interpreternek. Az alábbi képernyőkép a Python interpretert mutatja egy Ubuntu Linux konzolban.
A Pythonhoz tartozó ökoszisztéma igen bő, mely magába foglal számos fejlesztői környezetet és csomagkezelőt. Ezek között említünk meg néhányat:
pip
csomagkezelővel a különböző prgramocsomagokat tudunk telepíteniA Spyder fejlesztői környezet (Anaconda tartalmazza) egy a Matlabban megszokott felületet kapunk.
IPython
(Interactive Python) egy “kernel”, mely lehetővé tesz interaktív számításokat.Jupyter Notebook egy web alapú notebook környezetet szolgálatat az
IPython
kernelhez a Mathematica vagy Matlab notebookjaihoz hasonlóan.Az Anaconda ingyenes környezet segítségével egyszerűen telepíthetünk 250 olyan programot, amelyet mérnöki, tudományos számításokhoz használhatunk. Anaconda telepítésével megkapjuk a Spyder és Jupyter Notebook progarmokat is. Egyszerű telepítése miatt ajánlott kezdő felhasználóknak.
Visual Studio Code az egyik legnépszerűbb általános célú ingyenes fejlsztői környezet, melyhez Python kiegészítő is tartozik. Hatékonyan használható Python fejleszésre. A Python kiegészítő IPython interfészt is biztosít.
Spyder felhasználói felülete:
Visual Studio Code felhasználói felülete:
Colab környezet#
Colab egy a Google által nyújtott, részben ingyenes, IPython
kernelt futtató Jupyter Notebook típusú felhő szolgáltatás. Bejelentkezéshez Google email fiókkal kell rendelkeznünk, mely ugyancsak ingyenesen létrehozható. Mivel ez egy felhő szolgáltatás, a kódok végrehajtása nem a saját számítógépünkön, hamen a Google által üzemeltetett szerveren történik: a böngészőnkben csupán a kódot írjuk.
A kódot a Colab webes felület celláiban adhatjuk meg. A kódot cellákba renszerezzük. Ezután a cellákat tudjuk külön-külön futtatni:
Egyenként futattatni a cellákat
shift
+Enter
vagy a ▶ gombra kattintva lehet. Valamennyi időbe beletelhet a kernel elindítása, lásd lejjebb.Minden cellát futtatni fentről lefele:
Runtime
→Run all
Kernel újraindítása:
Runtime
→Restart runtime
A kód futtatása a következő képpen zajlik a háttérben:
A cella elküldésre kerül a Google szerveihez, majd
a szerveren egy dedikált kernelen a kód lefut,
ezután a futás eredménye vissza küldésre kerül a webböngészőnkbe.
A Python kernel dedikált az éppen aktuális notebookhoz, ezért a létrehozott változók, fájlok megmaradnak a cellák közötti futtatások során. A kernel újraindítása szükséges ahhoz, hogyha a korábban létrehozott változóinkat szeretnénk töröljni, és ha egy friss kernellel szeretnénk újrakezdeni. Az első cella futtatása hosszabb ideig eltarthat, mivel a szerver ilyenkor indítja el a kernelt. Amennyiben hosszabb ideig nem végzünk interakciót a Colabban, a szerver lezárja a kapcsolatunkat és leállítja a kernelt; ekkor minden változónk, fájlunk elvész.
Tipp
Ha valami hibát kapunk, az jó eljárás, hogy eltöltünk 1-2 percet a hiba keresésével, hátha valami triviális. Ha nem megy akkor, indítsuk újra a kernelt és futassuk újra az összes cellát. Ez egy menü elemmel is elérhető: Runtime
→ Restart and run all
. Ha a hiba ezek után is fent áll, akkor további hibakeresésre van szükség.
Figyelem
Ha hosszabb ideig nem végzünk műveleteket a Colab környezetbe, akkor a kernel a háttérben már leállt, ezért minden eddigi számításunk elveszett. Ilyenkor szükséges az összes cella újbóli futattása a Runtime
→ Run all
menüvel
Hello world!#
A “Hello world!” program egy olyan kód, ami a címben szereplő szöveget írja ki a képernyőre. Ez egy olyan egyszerű program ami demonstrálja, hogy a fordító/fejlesztési környezet készen áll a használatra. További információ és példa “Hello world!” programok a wikipédián található.
Írjuk meg legelső Hello world programunkat, és próbáljuk meg értelmezni!
print("Hello world!")
Hello world!
Változók#
Változó: Egy Exceles analógiát véve, a változókat úgy képzelhetjük el mint a cellákat az Excel-ben: valamilyen értékeket hozzá tudunk rendelni egy-egy változóhoz, majd azokon műveleteket tudunk végrehajtani. A különbség itt, hogy míg Excelben a $ jellel jelöljük meg a cellákat, itt erre nincs szükség.
Figyelem
A változókat mindig szöveges karakterrel kezdődik, majd ezt követően tartalmazhat ékezet nélküli betüket, számokat, és kevés speciális karaktereket. Általában az alábbi speciáls karaktereket szoktuk használni változó nevekben:* _
, $
.
Törekedjünk értelemes változó nevek megadására, így könnyebben olvasható a kód.
Tipp
Jó ökölszabály arra gondolni, hogy olyan változónevet válasszunk, amelyet felhasználónévként is megadhatnánk egy weboldal regisztrációja során.
A következő példa mutatja, hogyan rendelhetünk értéket egy változóhoz. Az Exceles analógiával élve, ezt úgy képzelhetjük el, hogy a művelet megfelel az Excel cellába történő valamilyen érték megadásának.
pi = 3.21
hello_world_string = "Hello world!"
data_1 = 5321
Kiegészítő anyag
Mivel spacet nem használhatunk változó nevekben, ezért a gyakorlatban az öszetett szavakból álló változó nevekhez különböző gyakorlatok terjedtek el.
# Pascal case konvenció:
PascalCaseVariable=1
# Camel case konvenció:
camelCaseVariable = 1
# Snake case konvenció:
snake_case_variable = 1
Egyszerű típusok#
Az egyszerű típusok, olyan típusok, amelyekből más típusok felépíthetőek, vagy rendszerezésükkel más összetett adattípusok vezethetőek le. Az egyszerű típusokat a programozási nyelv alapértelmezetten definiálja, így bármilyen könyvtár használata nélkül elérhetőek. Megjegyezzük, hogy ez nem zárja ki azt, hogy összetett adattípusokat a nyelv alapértelmezetten definiáljon, mint ahogy azt később látni fogjuk a listák, szótárak esetén. Pythonban egyszerű típusok például az egész, lebegőpontos szám, a szöveg, vagy a logikai érték (boolean). Ahogy az Excelben a celláknak, úgy a változóknak is van típusa, pl. dátum, szöveg, szám.
Példa egész szám definiálása:
test_int = 1
print(test_int)
print(type(test_int))
1
<class 'int'>
A fenti kódban, először az 1
-t értékül adjuk a test_int
voltozónak, majd annak értékét kiírjuk. A type(...)
függvény megadja a változó típusát, amit a kiírásnál az utolsó sorban láthatunk.
Lehetőségünk van egyidejüleg több változónak is az értékét meghatározni az alábbi módon:
a, b, c = 1, 2, 3
print(a)
print(b, c)
1
2 3
Kiegészítő anyag
Erősen típusos nyelveknél a válozók értékadása két elkülünölő lépésből áll: a változó deklarálásából és annak inicializálásából. A deklarálás alatt a változó típusát adjuk meg, inicializáláskor pedig megadjuk annak kezőértékét. Nézzünk egy példát C++ nyelven: int a = 1;
Itt az a
változó int
(egész) típusát deklaráljuk, majd a változó értékének 1-t adunk. Az a
változó típusa ezután nem változhat meg: annak mindenkor valamilyen egész típust kell tárolnia. Gyengén típusos nyelvek esetén - amilyen a Python is - a deklarálás és inicializálás nem válik el élesen. A változó típusa az inicializáláskor megadott értéket veszi fel, mely típus futás során dinamikusan bármikor megváltozhat.
Lebegőpontos szám definiálása:
test_float = 0.13242
print(test_float)
print(type(test_float))
0.13242
<class 'float'>
Láthatjuk, hogy a változó float, azaz lebegőpontos (tizedestört) számot vett fel.
Figyelem
A tizedes jel a programozási nyelvek világában a pont .
nem pedig a vessző ,
. Ez egy fontos különbség az Excelhez képest, ahol a lokalizációs beállításoktól függően, lehetőségünk van tizedes vessző használatára. A pont használatának oka, hogy a programozási nyelveket elsődlegesen az angolszász világ terjesztette el, és a angol nyelv a tizedes pontot használja. Ugyancsak vegyük észre, hogy nem áll módunkban az ezresek jelőlése sem ponttal, sem pedig vesszővel.
Egy másik fontos egyszerű típus a logikai érték (bool
):
test_logical = True
print(test_logical)
test_logical = False
print(test_logical)
print(type(test_logical))
True
False
<class 'bool'>
Értelmezzük a következő kifejezést! Vegyük észre hogy a ==
összehasonlítást, míg az =
az értékadást jelentő egyenlőség jelek. Az összehasonítás eredménye True vagy False, azaz igaz vagy hamis érték lehet, aminek a típusa bool
. Az alábbi kód a False
értéket fogja kiírni, mivel a 1 == 2' kifejezés értéke
False, amit értékül adunk a
test_logic` változónak.
test_logical = (1 == 2)
print(test_logical)
False
Ezzel szemben az alábbi kód a True
értéket fogja kiírni, mivel a 1 == 1
kifejezés értéke True
, amit értékül adunk a test_logic
változónak.
test_logical = (1 == 1)
print(test_logical)
True
Pythonban elérhetőek logikai műveleteket, mint például and
, or
, not
:
print(not True)
print(True or False)
print(True and False)
print(False and True)
False
True
False
False
Logikai műveletek eredményeit igazságtáblákba foglalhatjuk. Néhány gyakran használt szabály:
or
kifejezés akkor igaz ha valamelyik operandus igaz, ésand
kifejezés akkor igaz ha mindkét operandus igaz.
Hasonlóan a valós számok körében megismert azonossádokhoz, a logikai műveleteken esetén is ismert számos azonosság. Például ellenőrízzük le De Morgan azonosságot:
print((not (True and False)) == (not True or not False))
True
Feladat
Gyakorlásképpen nézzük meg mit ír ki a következő kód!
a = 1
b = 2
test_logical = (a == 1) or not (a == b)
print(test_logical)
Másik gyakran használt egyszerű típus a szövek. Szöveg definiálása dupla vagy szimpla aposztrófok között lehetséges a következő módon:
variable = "hello"
print(variable)
print(type(variable))
variable = 'hello'
print(variable)
print(type(variable))
hello
<class 'str'>
hello
<class 'str'>
Tipp
Érdemes a hibaüzeneteket tanulmányozni, sokat segíthet kódolási hibák megtalálásában.
De '
és "
egymásba ágyazhatóak, mint például:
print('Az mondta: "menj tanulni!"')
Az mondta: "menj tanulni!"
Figyelem
Az alábbi kód azonabn hibás, mert '
és "
keverve van, nem pedig egymásba ágyazva:
variable = 'hello" # SyntaxError: EOL while scanning string literal
Műveletek egyszerű típusokkal#
Műveleteket változók között definiálhatunk. Unáris műveleteken, olyan műveleteket értünk, melynek egy operandusa van, pl. abszolút érték művelete. Bináris műveletnek két operandusa van, a leggyakrabban használt műveletek ilyenek, pl. összeadás, szorzás.
Szám típusú változókkal történő matematikai műveletek úgy működnek, ahogy ezt máshol is megszokhattuk, pl. Excelbe.
pi = 3.14
r = 5.0
K = 2.0*r*pi
print('K értéke:', K)
K értéke: 31.400000000000002
A műveletek kiértékelése balról jobbra történik a zárójelek és a matematikában megszokott precedenciák (műveleti sorrend) szerint. Törtek esetén különösen figyeljünk a matematikában megszokott kifejezések helyes kódolására. Erre példaként nézzük a \(\dfrac{a}{b*2}\) kifejezést:
b = 2.0
a = 2.0
print(a/b*2) # nem az eredeti tört kifejezés
print(a/(b*2)) # helyesen
2.0
0.5
Az összeadás művelete szövegek esetén is értelmezett. Ekkor a szövegek összefűzéséről, vagy konkatenációjáról beszélhetünk, amikor két szöveg egy olyan új szöveggé válik, amely a bal oldali majd jobb oldali szövegek karaktereit tartalmazza:
hello_world = "Hello " + "world!"
print(hello_world)
Hello world!
És egy másik példa a függvény parametér listájában megadott műveletre:
name = "Joe";
hello = "Hello"
print(hello + " " + name + "!")
Hello Joe!
A fenti kódrészlet utolsó sorát a következő képpen kell olvasni:
először a
hello + " " + name + "!"
kifejezés balról jobbra kerül végrehajtásra, mely az egyes szöveg típusok konkatenációjat jelentik. Így egy köztes érték jön létre, mely aHello Joe!
szöveg,majd a köztes érték kerül a függvénynek átadásra. A függvényekről, még később bővebben lesz szó.
Ezután nézzük meg a hatványozást Pythonban, melynek műveleti jele a **
:
T = r**2.0*pi
print(T)
78.5
Hatványozással négyzet gyök is kifejezhető. Az alábbi példában, egy új alapértelmezetten definiált típust is láthatunk, amikor a -9 negyzetgyökét vonjuk:
a = -9
print(a**(1/2))
(1.8369701987210297e-16+3j)
Feladat
Egy példa, melyben minden alapművelet szerepel. Mit csinál az alábbi kód? Mit fog kiírni a kód?
a, b, c = 2, 0, 0
x1 = (-b + (b**2 - 4*a*c)**0.5) / (2*a)
x2 = (-b - (b**2 - 4*a*c)**0.5) / (2*a)
print(x1 == x2)
Típus konverziók#
Nagy általánosságban, bináris műveleteket csak azonos típusok között értelmezzünk, melynek eredménye a kérdéses típus lesz. A fenti példában nézzük meg a változók típusát:
pi = 3.14
print('pi típusa:', type(pi))
r = 5.0
print('r típusa:', type(r))
K = 2.0*r*pi
print('K értéke:', K)
print('K típusa: ', type(K))
pi típusa: <class 'float'>
r típusa: <class 'float'>
K értéke: 31.400000000000002
K típusa: <class 'float'>
Amennyiben a két típus nem azonos, akkor típuskonverzióra van szükség.
Figyelem
Nézzünk meg egy példát, amely során int
típust akarunk str
típussal összeadni. Az alábbi kód hibával fog leállni:
age = 22
message = age + " éves vagyok" # Error: TypeError: unsupported operand type(s) for +: 'int' and 'str'
print(message)
Hibát kapunk, mivel, habár egészek és szövegek között az összeadás művelete értelmezett, de egész és szöveg között nem. Nézzük meg az összeadásban resztevevő opreandusok típusát:
age = 22
print('bal operandus: ', type(age))
print('jobb operandus: ', type(" éves vagyok!"))
bal operandus: <class 'int'>
jobb operandus: <class 'str'>
Tehát típuskonverzióra van szükség. Valamilyen típust szöveggé az str()
függvény segítségével tudunk szöveg típussá alakítani:
age = 22
print('age típusa:', type(age))
age_str = str(age) # <-- típus konverzió az str(..) függvény segítségével
print('age_str típusa:', type(age_str))
message = age_str + " éves vagyok!"
print('message értéke:', type(age_str))
age típusa: <class 'int'>
age_str típusa: <class 'str'>
message értéke: <class 'str'>
Vagy röviden:
age = 22
message = str(age) + " éves vagyok!"
print(message)
22 éves vagyok!
Feladat
Valamilye típust egésszé az int()
, valamint lebegő pontossá a float()
függvényekkel konvertálhatunk. Nézzük meg mit ír ki az alábbi kód. Mi történik a float
típussal amikor int
típusra konvertálódik?
pi = 3.1415
print('val_float értéke: ', pi)
print('val_float típusa: ', type(pi))
pi_int = int(pi) # típuskonverzió float -> int
print('val_float értéke: ', pi_int)
print('val_float típusa: ', type(pi_int))
Nézzük meg a következő példát:
test_float = 1.2
test_int = 1
test_result = test_float * test_int
print(test_result)
1.2
Nézzük meg a műveletben résztvevő változók típusát:
test_float = 1.2
print(type(test_float))
test_int = 1
print(type(test_int))
test_result = test_float + test_int
print(type(test_result))
<class 'float'>
<class 'int'>
<class 'float'>
Láthatjuk, hogy az összeadás bal oldalán lebegőpontos, jobb oldalán egész típus található, az eredmény pedig lebegőpontos. Talán elsőre triviális, de vegyük észre, hogy a háttérben típus konverzió történik. Ez a típus konverzió automatikus, ezért automatikus típuskonverzióról beszélünk. A következő lépések történnek a háttérben, amikor a test_result = test_float + test_int
művelet végrehajtódik:
Mivel a szorzás két oldán különböző típus szerepel, a
test_int
változóint
típusafloat
típussá konvertálódik.Ez a közbenső
float
típussú érték kerül szorzásra atest_float
float
típusú változóban található értékkel.Mindkét oldalon
float
típus található, így az eredmény isfloat
lesz, amely atest_result
változóba kerül.
Más szavakkal a következő kód fog lefutni:
test_result = float(test_float) + test_int
Egy másik kód részlet, amely a kör kerületét adja meg:
pi = 3.14
r = 5
K = 2*r*pi
print(type(K))
print(K)
<class 'float'>
31.400000000000002
Itt az r
sugár int
típusként van definiálva, melynek értéke a szorzás művelet során float
típusúvá válik. Vegyük észre, hogyha a pi
float
típus kerülne int
konverzióra, akkor rossz eredményt kapnánk, hiszen a tizedes értékek levágásra kerülnének. Elmondható tehát, hogy automatikus típuskonverzió esetén a kisebb halmazú típus kerül a nagyobb halmazú típusra konvertálásra.
A kód szintaktikája és szemantikája#
Szintaktika alatt a programozási nyelvet leíró “nyelvtant”, szabályrendszert értjük, például milyen elnevezése lehet egy változónak, vagy hogy hogyan definiálunk értékadást, függvényeket. Ezzel szemben a szemantika alatt a program “értelmét” értjük, vagyis azt hogy helyesen működik-e vagy sem.
Nézzünk egy példát az elő nyelvből:
A ég kék.
Ez a mondat helytelen, mivel az “ég” határozott névelője “az”. Ez egy szintaktikai hiba.
Az ég piros.
Ez a mondat nyelvtanilag helyes, tehát szinaktikai hiba nincs. Ellenben az ég nem piros; ez szemantikai hiba.
Ökölszabály, ha a kód szintaktikailag nem helyes, akkor mindenképpen hibaüzenetet kapunk. Valamilyen fejlesztő eszközt használva, az automatikus kódelemzők a legtöbb esetben már futás előtt jelzik a hibát. Nem interpretált nyelvek esetén - tehát olyan programozási nyelvek esetén, ahol szétválik a fordítás és a futtatás - a szintaktikai hiba már fordítási időben kiderül. Ezzel szemben, egy szemantikailag helytelen program esetén a hibára fordítási időben nem derül fény. Jó példa szemantikai hibára a tömbök túlcímzése, vagyis amikor egy tömb vagy vektor olyan elemére hivatkozunk, amely túlmutat a tömb hosszán.
Függvények#
Függvényekkel már találkoztunk korábban, ilyen volt a print
. A print
egy alapértelmezetten definiált függvény, azonban saját magunk is írhatunk függvényeket.
A függvények - hasonlóan a matematikában megtanultakhoz - valamilyen bemeneti értékre (független változó) adnak valamilyen kimenetet (függő változó). Azonban, szemben a matematikai függvényekkel, a programozási nyelvek függvényeinek nem feltétlenül van bemeneti paramétei (argumentumai), illetve nem feltétlenül van kimenetük (visszatérési érték). Függvényekre gyakran eljárásként hivatkoznak. A függvények egy speciális esete, az olyan függvény, melynek nincs bemeneti paramétere; ekkor használhatjuk a metódus elnevezést a függvényre.
Egy függvény komplex dolgokat oldhat meg, melynek során további függvényeket is meghívhat. A függvények célja hogy logikailag összetartozó kódot egy egységbe foglaljanak, így növelje a kód újrafelhasználhatóságát és olvashatóságát. Vegyük észre, hogy a függvény használója számára nem érdekes hogy egy bizonyos feladatot a függvény hogyan old meg, csupán az, hogy mik a bemeneti paraméterei és kimeneti értékei. Így a feladat megoldásának mikéntje a függvény feladata. A függvény bemenetét leíró paraméter listát és a visszatérési értéket együtt a függvény szignatúrájának hívjuk.
A Python nyelvben a függvények szintaktikája a következő:
def hello(name):
my_string = 'Hello ' + name + "!"
print(my_string)
Feladat
Elemezzük a fenti kódot és definiáljuk a függvény szintaktikáját! Azonosítsuk a következőeket:
bemeneti paraméter
függvény neve
függvény törzse
Vegyük észre, hogy a fenti kód részletben a függvény törzsének definiciója be van húzva spaceszel vagy tabbal (ezeket közös néven whitespace karaktereknek hívjuk). Ezeket a whitespaceket hívjuk rossz magyarsággal indentálásnak. Pythonban a sor eleji whitespace karakterek fontos jelentőséggel bírnak, hogy megkülönböztessünk függvény törzs, illetve más vezérlési szerkezetek belső részét. Mindig figyelj oda, hogy a sor eleji whitespacek megfelelőek legyene, máskülönben hibát fogsz kapni.
Figyelem
Példaként nézzünk meg néhány identálási hibát:
def hello(name):
name = 'Anna'
print(name) # hiba: egy szóköz hiányzik
hello('Anna') # hiba: egy szóköz felesleges
# Helyes identálással:
def hello(name):
name = 'Anna'
print(name)
hello('Anna')
Az így definiált függvényt más cellákban is meg tudjuk hívni.
hello("Joe")
hello("Jane")
Hello Joe!
Hello Jane!
Ahogy említettük korábban, a függvényeknek lehet visszatérési értéke, melyet a return
kulszóval adhatunk meg. A következő függvény egy kör területét számítja ki, és amelynek a bemeneti paramétere a kör sugara:
def circle_area(r):
T = r**2*3.14145
return T
Számítsuk ki az 5 sugarú kör területét:
r = 5
T = circle_area(r)
print("Egy " + str(r) + " sugarú kör területe: " + str(T))
Egy 5 sugarú kör területe: 78.53625
A python nyelveben egy függvénynek több visszatérési értéke is lehet, melyeket vesszővel elválasztva a return
kulcsszó után adhatunk meg:
def circle_params(r):
K = 2*r*3.14145
T = r**2*3.14145
return K, T
A függvény hívásakor, a többszörös visszatérési értékeket, a bal oldalon, vesszővel elválasztva adhatjuk meg:
K, T = circle_params(5)
print('A kör kerülete: ', K)
print('A kör területe: ', T)
A kör kerülete: 31.414499999999997
A kör területe: 78.53625
Függvénynek lehet ún alapértelmezett paramétere. A bemeneti paraméter alapértelmezett értékét függvény bemenetének megadásakor adhatjuk meg az egyenlőség jelet használva. Nézzünk egy példát:
def circle_area(r=1):
T = r**2*3.14145
return T
Az alapértelmezett paraméter, egy olyan bemeneti paraméter, amelyet nem kötelező megadni. Így például a circle_area
függvényt paraméter nélkül is hívhatjuk:
print("Egység sugarú kör területe: " + str(circle_area()))
Egység sugarú kör területe: 3.14145
De lehetőség van a sugar megadására is, ha akarjuk:
print("Egy 5 sugarú kör területe: " + str(circle_area(5)))
Egy 5 sugarú kör területe: 78.53625
Feladat
A következőekben nézzünk egy példát egy komplex kódra, mely egy gyakran alkalmazott geodéziai számítást old meg. Vegyük észre, hogy a függvény egy jól körülhatárolt problémát old meg, melynek bemenetei és kimenetei tisztán adottak.
Milyen geodéziai problémát old meg az alábbi kód?
Mi a függvény szignatúrája? Mik a bemeneti és kimeneti paraméterek?
Mi a célja az alapértelmezett paraméternek?
Van-e sorrendi megkötés az alapértelmezett és nem alapértelmezett paramétereknek? Például felcserélhető-e a
lan
ésellipsoid
paraméterek?Teszteljük a kódot a BUTE állomás koordinátáival.
import math
def llh2ecef(lat, lon, alt, ellipsoid='wgs84'):
rad_lat = lat * (math.pi / 180.0)
rad_lon = lon * (math.pi / 180.0)
if ellipsoid == 'wgs84':
a = 6378137.0
finv = 298.257223563
else:
print('Unknown ellipsoid')
return
f = 1 / finv
e2 = 1 - (1 - f) * (1 - f)
v = a / math.sqrt(1 - e2 * math.sin(rad_lat) * math.sin(rad_lat))
x = (v + alt) * math.cos(rad_lat) * math.cos(rad_lon)
y = (v + alt) * math.cos(rad_lat) * math.sin(rad_lon)
z = (v * (1 - e2) + alt) * math.sin(rad_lat)
return x, y, z
llh2ecef(47.4809437284, 19.0565297521, 180.811)
# Eredmény: (4081882.3780616224, 1410011.1419668908, 4678199.39132865)
Változók láthatósága és névterek (scope)#
Ahogy korábban beszéltünk róla, a függvények logikailag összetartozó kód sorokat fognak össze. A függvény használója számára nem érdekes az, hogy a program a feladatot hogyan oldja meg, ő csak a számításhoz szükséges paramétereket akarja átadni, és az eredményet megkapni. A függvényen belül azonban lehetőségünk van változók létrehozására, manipulálására. Azért, hogy ezek a változók a függvényen kívülről ne legyenek elérhetőek, a programozási nyelvek a változók számára láthatóságot, illetve hatókört definálnak. Ezzel elkerülhető, hogy változó névadási bonyodalmakba keveredjünk.
Nézzük meg az alábbi kódot:
name = 'Anna' # globális névtér
def hello(): # globális névtér
name = 'Béla' # a függvény névtere
print(name) # a függvény névtere
hello() # globális névtér
print(name) # globális névtér
Béla
Anna
A fenti kódban a name
változó a függvényen kívűl kerül definiálásra, majd egy másik name
változó a függvényen belül. Két esetben írjuk ki a name
-k értékét: egyszer a függvényen kívül az utolsó sorban, máskor a függvényen belül a hello()
függvény hívásakor. Vegyük észre, hogy az eredmény sorrendje: Béla
, Anna
. Ha a függvényen belüli name = 'Béla'
sort nézve a name
változó a külső name
változóra hivtkozna, akkor az utolsó sorban lévő print
nek az Anna
szöveget kéne kiírnia, hiszen a függvényen belül az megváltozott. De nem ez történik, mivel a két name
változót, bár ugyanaz a karakterlánc reprezentálja, de azok mégis különböző változók. Különbözőségüket az adja, hogy más-más helyen vannak definiálva. A függvényen kívűl létrehozott változók, az ún. globális névtérben kerülnek létrehozásra. A függvény törzsében létrehozott változók csak a függvény névterében érhetőek el.
Feladat
Próbáljuk meg futtatni az alábbi kódot! Miért áll le a program hibával?
def hello():
name_hello = 'Anna'
print(name_hello)
hello()
print(name_hello) # hiba: NameError: name 'name_in_hello' is not defined
A fenti feladatban lévő kód kis változtatással lefut:
name = 'Anna'
def hello():
print(name)
hello()
print(name)
Anna
Anna
A kód lefut, mivel a name
változó a függvényen kívül került létrehozásra, a globális névtérben. A globális névtérben létrehozott változók elérhetőek a függvények belsejében.
Tehát a változók és névterekre vonatkozó szabályok a következőek:
A globális névtérben létrehozott változók mindenhol, még függvények belsejében is elérhetőek, ha azok a függvény definiálása előtt kerültek létrehozásra.
A függvények belsejében lévő változók csak az adott függvényen belül érhetőek el.
Végezetül, bár triviális, a függvény paramétere a függvény névteréhez tartozik. Nézzünk egy példát:
name = 'Anna'
def hello(name):
print(name)
hello('Béla')
print(name)
Béla
Anna
Feladat
Mit ír ki a következő kód és miért?
name = 'Anna'
def hello(name):
name = 'Béla'
print(name)
print(name)
hello('Cecília')
print(name)
Feladat
Mit ír ki a következő kód és miért?
name = 'Anna'
def hello1():
print(name)
def hello2():
name = 'Béla'
print(name)
print(name)
hello1()
hello2()
print(name)
Hívási verem#
Kiegészítő anyag
Ez a rész kiegészítő anyag és csak a függvényhívások mélyebb megértését segíti.
Hívási veremről további info: https://towardsdatascience.com/python-stack-frames-and-tail-call-optimization-4d0ea55b0542
Rekurziós függvények#
A rekurziós függvények olyan függvények, amelyek önmagkuat hívják. Klasszikus rekurziós példa a Fibonaci sorozat:
def recur_fibo(n):
if n <= 1:
return n
else:
return(recur_fibo(n-1) + recur_fibo(n-2))
recur_fibo(20)
6765
print(recur_fibo(1), recur_fibo(2), recur_fibo(3), recur_fibo(4), recur_fibo(5), recur_fibo(6), recur_fibo(7))
1 1 2 3 5 8 13
Feladat
Hozzunk példát más rekurziós függvényre!
Függvény könytárak és import
#
A python egyik nagy erőssége, és az ok, hogy annyira népszerű, a kiterjedt és sokféle feladatra használható ingyenes függvénykönyvtárai. Leegyszerűsítve egy könyvtár hasonló változók és függvények gyűjteménye. Egy könyvtárat az import
kulcsszóval tudunk betölteni:
import math
Egy könytáron belüli változóra vagy függvényre hivatkozni a könyvtár neve és a .
jel segítségével tudunk, például:
print(math.pi)
3.141592653589793
A következő példa, a könyvtár használatát mutatja be egy korábbi függvényünkben. Itt a pi
értékét nem mi definiáljuk, hanem a könyvtárból vesszük:
def circle_area(r=1):
T = r**2*math.pi
return T
print("Egység sugarú kör területe: " + str(circle_area()))
Egység sugarú kör területe: 3.141592653589793
Elhagyható a könyvtár nevére való hivatkozás, amennyiben a from ... import ...
kulcsaszavakkal a függvényt direktbe importájuk:
from math import pi
print(pi)
3.141592653589793
Nézzünk példát egy másik könyvtár használatára:
import time
Egy könytáron belüli változóra vagy függvényre hivatkozni .
segítségével tudunk, például:
t = time.localtime()
current_time = time.strftime("%Y/%m/%d %H:%M:%S", t)
print(current_time)
2024/05/02 09:51:17
t = time.localtime()
current_time = time.strftime("%Y év %m hónap %d nap %H óra %M perc %S mp", t)
print(current_time)
2024 év 05 hónap 02 nap 09 óra 51 perc 17 mp
Az as
kulcszó segítségével átnevezhetjük a könyvtárat, így nem kell az eredeti hosszú névre hivatkozni:
import time as t
local = t.localtime()
current_time = t.strftime("%Y/%m/%d %H:%M:%S", local)
print(current_time)
2024/05/02 09:51:17
Elhagyható a könyvtár nevére való hivatkozás, amennyiben a from ... import ...
kulcsaszavakkal a függvényt direktbe importájuk:
from time import localtime, strftime
t = localtime()
current_time = strftime("%Y/%m/%d %H:%M:%S", t)
print(current_time)
2024/05/02 09:51:17
Tipp
A help
függvény segítségével kaphatunk információt egy függvényről, például:
help(strftime)
help(strftime)
Help on built-in function strftime in module time:
strftime(...)
strftime(format[, tuple]) -> string
Convert a time tuple to a string according to a format specification.
See the library reference manual for formatting codes. When the time tuple
is not present, current time as returned by localtime() is used.
Commonly used format codes:
%Y Year with century as a decimal number.
%m Month as a decimal number [01,12].
%d Day of the month as a decimal number [01,31].
%H Hour (24-hour clock) as a decimal number [00,23].
%M Minute as a decimal number [00,59].
%S Second as a decimal number [00,61].
%z Time zone offset from UTC.
%a Locale's abbreviated weekday name.
%A Locale's full weekday name.
%b Locale's abbreviated month name.
%B Locale's full month name.
%c Locale's appropriate date and time representation.
%I Hour (12-hour clock) as a decimal number [01,12].
%p Locale's equivalent of either AM or PM.
Other codes may be available on your platform. See documentation for
the C library strftime function.
És hogy itt áljon egy példa, hogy mindenre van egy könyvtár Pythonban: jelenítsük meg 1848 márciusának naptárját alfanumerikusan:
import calendar
print(calendar.month(1848, 3))
March 1848
Mo Tu We Th Fr Sa Su
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Feladat
Importáljuk a
__hello__
könyvtárat! Mit kapunk?Importáljuk a
this
könyvtárat! Mit kapunk? Ez egy easter egg.
Az elágazás: if
… else
és elif
#
Az elágazás lehetővé teszi a kód sorról-sorra való végrehajtásának megtörését. Amennyiben az elágazás feltétele igaz, az elágazás blokkja végrehajtódik, különben az elágazás törzsében lévő kód nem kerül végrehajtásra. Íme egy példa:
a = 1
if a >= 1:
print("true")
print("end")
true
end
Feladat
Elemezzük a fenti kódot és definiáljuk az elágazás szintaktikáját! Azonosítsuk a következőeket:
az elagazás feltétele
az elágazás blokkja
Az elágazás feltételének valamilyen logikai értékre, tehát True
vagy False
ra kell kiírtékelődnie. A fenti példában például láthatjuk, hogy az összehasonlítás igazat, vagy hamisat ad:
print('Feltétel értéke: ', a >= 1)
print('Feltétel típusa: ', type(a >= 1))
Feltétel értéke: True
Feltétel típusa: <class 'bool'>
Megjegyezzük, hogy az automatikus típuskonverzió révén más típusok is szerepelhetnek a feltételben. Ekkor létezni kell egy a típusról logikai értékre történő alapértelmezett (automatikus) konverziónak. Így például számok esetén, a 0 érték False
, míg a nem nulla érték True
logikai értékké konvertálódik:
print('0 -> bool konverzió:', bool(0))
if not 0:
print('0: A feltétel: False')
print('100 -> bool konverzió:', bool(100))
if 100:
print('100: A feltétel: True')
0 -> bool konverzió: False
0: A feltétel: False
100 -> bool konverzió: True
100: A feltétel: True
A fenti kódrészletben a bool
függvény segítségével direkt típuskonverziót használtunk, hogy megmutassuk a típuskonverzió értékét. Ezután az if
feltételekben a bool
függvényt már nem használtuk, így automatikus típuskonverzió révén kerül a feltétel kiértékelésre.
Az else
ág lehetőséget ad arra, hogy olyan kód blokkot adjunk meg, amely abban az esetben kerül végrehajtásra, ha a feltétel nem teljesül:
a = 0
if a >= 1:
print("if blokk")
else:
print("else ág")
else ág
Feladat
Ismételjük át a logikai műveletkeről tanultakat! Mit ír ki az alábbi kód?
a, b = 1, 2
if not (a == 2 or b == 2):
print('if blokk')
else:
print('else blokk')
Lehetőségünk van több feltételt megadni az elif
segítségével. A következő kód például megadja, hogy egy bizonyó órához, milyen étkezés tartozik:
hour = 10
if 0 <= hour < 10:
print("reggeli")
elif 10 <= hour < 17:
print("ebéd")
elif 17 <= hour < 24:
print("vacsora")
else:
print("nem létező idő a napon belül!")
ebéd
Feladat
Mit csinál az alábbi kód? Mi a probléma a kóddal? Teszteljük!
v = 0
if v < 0:
abs_v = -v
elif v > 0:
abs_v = v
print(abs_v)
Az if
szerkezetet egyszerű esetekben (amikor egy sorba lehetne írni a blokkot) kifejthetjük egy sorban is:
a = 1
print("true") if a == 1 else print("false")
true
A fenti kódrészletben a print("true")
akkor kerül végrehajtásra, ha az a == 1
feltétel igaz, máskülönben az else
utáni print("false")
kód kerül végrehajtásra.
Az egysoros if kifejezést használhatjuk feltételes változó értékadásra, ahogy az alábbi példában is:
a = 0
b = 1 if a == 1 else 2
print(b)
2
Vegyük észre, hogy a b = 1 if a == 1 else 2
kifejezésben, nem a b = 1
a kódrészlet, amely az igaz esetén kiértékelődik, hanem csupán az 1
. Ez azért lehetséges, mert az egysoros if
előrébb van a műveleti sorrendben mint az értékadás. Hogy érthető legyen, a fenti kód zárójelezve:
b = (1 if a == 1 else 2)
Végezetül, az if
blokkja nem definiál hatókört a változónak. Az alábbi kódban az if
blokkban létrehozott változó elérhető a globális névtérben is:
if True:
test = "Ez a változó az if blokkban lett létrehozva"
print(test)
Ez a változó az if blokkban lett létrehozva
A None
típus#
Egy változó felvehet None
típust, amit úgy értelmezhetünk, hogy a változónak nincs értéle:
var = None
A None értéket ellenőrízhetjök:
if var == None:
print("It is None!")
It is None!
Alpértelmezetten hamis az értéke egy if feltételben:
if var:
print("Condition is true!")
else:
print("Condition is false!")
Condition is false!
De vigyázzunk, maga az érték nem False
vagy True
, így a következő kifejezés nem működik:
if var == False:
print("Condition is true!")
else:
print("Condition is false!")
Condition is false!
if var == True:
print("Condition is true!")
else:
print("Condition is false!")
Condition is false!
A következő példa mutatja, mi a legjobb módja ellenőrizni egy változónak, hogy None
az értéke:
if var is None:
print("Condition is true!")
else:
print("Condition is false!")
Condition is true!
if var is not None:
print("Condition is true!")
else:
print("Condition is false!")
Condition is false!
Függvény változók#
Nézzük meg az alábbi kódot:
def hello(name):
print('Hello, Mr. ', name, '!')
hello('Smith')
Hello, Mr. Smith !
Minden ismert a fenti kód részletben: létrehozunk egy függvényt, melynek bemeneti értéke egy name
változó, melyet aztán kiír a függvény. Végül, az utolsó sorban kiírjuk a függvényt. Ezután nézzük meg az alábbi kódot:
def hello(name):
print('Hello, Mr. ', name, '!')
hello2 = hello
hello2('Smith')
print(type(hello2))
Hello, Mr. Smith !
<class 'function'>
Vegyük észre hogy a hello
literál egy függvény név, melyet értékül adunk a hello2
változónak. Ezután a hello2
-t használjuk, hogy meghívjuk az eredeti függvényt. Tehát a hello2
változó mögött a hello
függvény található. Ha megnézzük mi a hello2
változó típusát az utolsó sorban, akkor azt látjuk, hogy az egy függvény (function
). Ezeket a változókat hívjuk függvény változóknak.
Függvény változók segítségével bizonyos döntési pontokat a kódban szabadon rendezhetünk. Például lásd az alábbi kódot:
def hello_mr(name):
print('Hello, Mr. ', name, '!')
def hello_mrs(name):
print('Hello, Mrs. ', name, '!')
first_name = 'Jane'
# Döntési point
if first_name == 'Joe':
hello = hello_mr
else:
hello = hello_mrs
hello('Smith')
Hello, Mrs. Smith !
A fenti kódban, a személy megszólítása Mr. vagy Mrs. annak függvényében, hogy a személy keresztneve Joe vagy Jane. A kód először definiálja a két kiírási módot, majd a hello
változó felveszi valamelyik függvény változatát a kersztnév alapján. Ezután a hello
függvény meghívásakor a megfelelő megnevezés fog meghívódni.
A fenti példa egyszerűsége miatt erőltetettnek tűnhet, de gyakran hasznos. Egy gyakori példa, a kódban található ellenörző kódok kiírása (loggolás). A gyakorlatban bizonyos kiírásokat csak fejlesztéskor szeretnénk látni, hogy a fejlesztő ellenörizni tudja a kód belső működését, ezt hívjuk debug módnak. Amikor a programot kiadják, tehát elérhetővé teszik a végfelhasználó számára (release mód), akkor ezeket a kiírásokat nem szeretnénk a felhasználó számára láthatóvá tenni. Egy lehetséges megoldás, hogy a kódbázison végigmenve kitörölni azokat a kódrészleteket, melyek ilyen kiírást végeznek. Ez manuálisan intenzív, illetve a folyamatos fejlsztéskor, ezekre a kódrészletkre szükségünk lehet. Nézzük meg az alábbi példát, hogyan oldhatjuk meg ezt egyszerűen függvényváltozó segítségével:
def log_debug(str):
print(str)
def log_release(str):
pass
mode = 'release'
log = log_debug
if mode == 'release':
log = log_release
# Komplikált számítás loggolással
import math
lat = 47.4809437284
lon = 19.0565297521
alt = 160
rad_lat = lat * (math.pi / 180.0)
log(rad_lat)
rad_lon = lon * (math.pi / 180.0)
log(rad_lon)
a = 6378137.0
finv = 298.257223563
f = 1 / finv
e2 = 1 - (1 - f) * (1 - f)
log(e2)
v = a / math.sqrt(1 - e2 * math.sin(rad_lat) * math.sin(rad_lat))
log(v)
x = (v + alt) * math.cos(rad_lat) * math.cos(rad_lon)
y = (v + alt) * math.cos(rad_lat) * math.sin(rad_lon)
z = (v * (1 - e2) + alt) * math.sin(rad_lat)
print(x, y, z)
4081869.0840466293 1410006.5497940828 4678184.052527026
A fenti kód nem csak az eredményt írja ki az utolsó sorban, mivel release módban vagyunk. Ha a mode
változót megváltoztatjuk debug-ra a log
hívás ki fogja írni a köztes számítások értékét, melyet használhatunk. Tehát látható, hogy a két kiírási mód között egyszerűen egy változó értékének a megváltoztásával elegánsan tudunk váltani.
Másik gyakorlatban előforduló példa, amikor egy függvény hívásakor egy másik függvény belső állapotának értékeire is szükség van. Ekkor a függvény változó - mint bármely más változó - szerepelhet a függvény bemeneti paramétereként. Nézzük meg az alábbi példát:
def integral(fn, a, b):
return 0.5 * (fn(a) + fn(b)) * (b - a)
def poly(x):
return x**2/3 + x**(1/2)
val = integral(poly, 0, 0.12)
print(val)
import math
print(integral(math.sin, 0, 0.12))
0.021072609690826527
0.007182732437335162
A fenti példában az integral
függvény egy bemeneti fn
függvény integrálját számítja ki a trapéz szabály szerint. Látható, hogy a függvény szempontjából az hogy mi a függvény maga, nem számít, csak hogy valamilyen valós bemeneti értékre adjon egy valós kimenetet. Az integrálandó függvényt a poly
függvényben definiáljuk, melyet ezután át tudunk adni az integral
függvénynek, mely megadja az integrál közelítő értéket. Hasonló módon, az integral
függvényt a math
könyvtárban lévő szinusz függvényre is tudjuk alkalmazni.
Függvény változókat alkalmazó megoldásokkal gyakran találkozhatunk a Python különböző könyvtáraiban.
Névtelen vagy lambda függvények#
Nézzük meg az alábbi függvényt:
def fn(x):
return x**2/3 + x**(1/2)
print(fn(4))
7.333333333333333
Névtelen vagy lambda függvények, olyan függvények melyek törzsét helyben fejtük ki. A lambda függvények egyszerűsítenek a kódon, olvashatóbbá teszik azt. Nagy hátrányuk, hogy csak egy sornyi kód adható meg velük.
A fenti kód lambda függvénnyel kifejezve:
fn = lambda x: x**2/3 + x**(1/2)
hello(fn(4))
print(type(hello))
Hello, Mrs. 7.333333333333333 !
<class 'function'>
A lambda függvénynek, mint minden függvénynek van bemeneti és kimeneti paramétere. A bemeneti paraméter a lambda kulcszó után található lista, melyet a :
zár le. A lambda függvény értékadásra kerülhet egy változónak, ahogy az a fenti példában is látható. A változó függvény típusú változó lesz. A változó visszatérési értéke a :
utáni kód értéke.
Egy példa lambda függvényre két bemeneti változóval, amely egy téglalap két oldala alapján annak területét számítja ki:
A = lambda a, b: a*b
print(A(10, 2))
20
Nézzük meg, hogy lambda függvénnyel hogyan egyszerűsíthető a korábbi integrálos példánk:
def integral(fn, a, b):
return 0.5 * (fn(a) + fn(b)) * (b - a)
val = integral(lambda x: x**2/3 + x**(1/2), 0, 0.12)
print(val)
0.021072609690826527
Látható, hogy nincs szükség külön def
kulcsszóval a függvény definiálására, ezt helyben, a függvény hívásakor meg tudjuk adni.
Feladat
Tudunk-e olyan problémát találni, ahol függvény változók, vagy lambda függvények hasznosak lehetnek.