11. Listák¶
A lista értékek rendezett gyűjteménye. Azokat az értékeket, amelyek a listát alkotják elemeknek nevezzük. A listák hasonlóak a sztringekhez, amelyek a karakterek rendezett gyűjteményei, kivéve, hogy a lista elemei bármilyen típusúak lehetnek. A listákat és a sztringeket – és más gyűjteményeket, amelyek megőrzik az elemek sorrendjét – sorozatnak nevezzük.
11.1. A lista értékei¶
Többféle módon lehetséges egy új lista létrehozása; legegyszerűbb az elemek szögletes zárójelbe való felsorolása ([
és ]
):
1 2 ps = [10, 20, 30, 40] qs = ["alma", "eper", "barack"]
Az első példa egy lista, amely négy egész számot tartalmaz. A második lista pedig három sztringet tartalmaz. A lista elemeinek nem kell azonos típusúnak lennie. A következő lista tartalmaz egy szrtinget, egy valós számot, egy egész számot és (érdekességképpen) egy másik listát.
1 zs = ["hello", 2.0, 5, [10, 20]]
A listában szereplő másik listáról azt mondjuk, hogy beágyazott.
Végül azt a listát, amely nem tartalmaz elemeket, üres listának nevezzük, és []
jelöljük.
Ahogyan már korábban láthattuk, a változókhoz vagy a listákhoz tartozó listaértékeket paraméterként hozzárendelhetjük a függvényekhez:
1 2 3 4 szotar = ["alma", "sajt", "kutya"] szamok = [17, 123] ures_lista = [] print(szotar, szamok, ures_lista)["alma", "sajt", "kutya"] [17, 123] []
11.2. Elemek elérése¶
A listaelemek elérésének szintaktikája hasonló, mint a sztringek esetében – az index operátort használjuk: []
(ne tévesszük össze az üres listával). A zárójelben lévő kifejezés adja meg az indexet. Emlékezzünk arra, hogy az indexek 0-tól kezdődnek:
1 print(szamok[0])17
Bármilyen egész értéket visszaadó kifejezés használható indexként:
1 print(szamok[9-8])123
1 print(szamok[1.0])Traceback (most recent call last): File "<input>", so 1, in <module> TypeError: list indices must be integers or slices, not float
Ha egy olyan elemet akarunk elérni, amely nem létezik, futási idejű hibát kapunk:
1 print(szamok[2])Traceback (most recent call last): File "<input>", line 1, in <module> IndexError: list index out of range
Használhatjuk a ciklusváltozót lista indexként.
1 2 3 4 lovasok = ["háború", "éhínség", "pestis", "halál"] for i in [0, 1, 2, 3]: print(lovasok[i])
A cikluson belül minden alkalommal az i
változót használjuk a lista i.
elemének kiírtatására. Ezt az algoritmust nevezzük lista bejárásnak.
A fenti példa esetén nem szükséges vagy nem használja az i
indexet semmire, csak az elemek elérésére, így ez a direktebb verzió – ahol a for
ciklus megkapja az elemeket – kedveltebb lehet:
1 2 3 4 lovasok = ["háború", "éhínség", "pestis", "halál"] for h in lovasok: print(h)
11.3. A lista hossza¶
A len
függvény visszatér a lista hosszával, amely egyenlő a lista elemeinek számával. Amennyiben egy egész indexet használunk a lista eléréséhez, célszerűbb, ha a lista hosszát használjuk a ciklus felső értékeként egy konstans helyett. Így, ha a lista mérete megváltozik, nem szükséges végig követni a teljes programot és módosítani az összes ciklust, mivel bármilyen méretű lista esetén megfelelően fog működni:
1 2 3 4 lovasok = ["háború", "éhínség", "pestis", "halál"] for i in range(len(lovasok)): print(lovasok[i])
Az ciklus utolsó végrehajtása esetén, i
értéke a len(lovasok)-1
, amely az utolsó elem indexe. (De az index nélküli változat jobban néz ki!).
Habár a lista egy másik listát is tartalmazhat, a beágyazott lista egyetlen elemként szerepel a szülői listában.
A lista hossza 4:
1 2 hossz = len(["autó gyártók", 1, ["Ford", "Toyota", "BMW"], [1, 2, 3]]) print(hossz)4
11.4. Lista tagság¶
Az in
és a not in
Boolean típusú operátorok, amelyek megvizsgálják egy elem tagságát a sorozatban. Korábban a sztringeknél már használtuk, de listákkal és más sorozatokkal is működnek:
1 2 3 4 5 lovasok = ["háború", "éhínség", "pestis", "halál"] print("pestis" in lovasok) print("dezertálás" in lovasok) print("dezertálás" not in lovasok)
Az eredmény a következő:
True False True
Ez a módszer sokkal elegánsabb a beágyazott ciklusoknál, amit korábban az Informatikára jelentkezett hallgatók számának meghatározásához használtunk a Beágyazott ciklus beágyazott adatokhoz fejezetben:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 hallgatok = [ ("Jani", ["Informatika", "Fizika"]), ("Kata", ["Matematika", "Informatika", "Statisztika"]), ("Peti", ["Informatika", "Könyvelés", "Közgazdaságtan", "Menedzsment"]), ("Andi", ["Információs Rendszerek", "Könyvelés", "Közgazdaságtan", " Vállalkozási Jog"]), ("Linda", ["Szociológia", "Közgazdaságtan", "Jogi ismeretek", "Statisztika", "Zene"])] # Számold meg, hány hallgató vette fel az Informatikát. szamlalo = 0 for (nev, targyak) in hallgatok: if "Informatika" in targyak: szamlalo += 1 print("Az Informatikát felvett hallgatók száma:", szamlalo)
11.5. Lista műveletek¶
A +
operátor összefűzi a listákat:
1 2 3 4 a = [1, 2, 3] b = [4, 5, 6] c = a + b print(c)[1, 2, 3, 4, 5, 6]
Hasonlóképpen, a *
operátor megismétli a listát egy megadott számszor:
1 2 3 4 d = [0] * 4 print(d) e = [1, 2, 3] * 3 print(e)[0, 0, 0, 0] [1, 2, 3, 1, 2, 3, 1, 2, 3]
Az első példában [0]
-t négyszer ismétli.
A második példában az [1, 2, 3]
listát háromszor ismétli meg.
11.6. Lista szeletek¶
A szeletelő operátorok, ahogyan korábban a sztringeknél is láthattuk, működnek részlisták esetében is:
1 2 3 4 5 a_list = ["a", "b", "c", "d", "e", "f"] print(a_list[1:3]) print(a_list[:4]) print(a_list[3:]) print(a_list[:])
Az eredmény a következő:
['b', 'c'] ['a', 'b', 'c', 'd'] ['d', 'e', 'f'] ['a', 'b', 'c', 'd', 'e', 'f']
11.7. A listák módosíthatók¶
A sztringektől eltérően a listák módosíthatók, ami azt jelenti, hogy megváltoztathatjuk az elemeiket. Az értékadás bal oldalán az index operátor használatával az egyik elemet módosíthatjuk.
1 2 3 4 gyumolcs = ["banán", "alma", "eper"] gyumolcs[0] = "körte" gyumolcs[2] = "narancs" print(gyumolcs)['körte', 'alma', 'narancs']
A zárójel operátor a listákra alkalmazva bárhol megjelenhet egy kifejezésben. Ha a kifejezés bal oldalán jelenik meg, akkor megváltoztatja a lista egyik elemét, így a gyumolcs
lista első eleme fog cserélődni "banán"
-ról "körte"
-re, és az utolsó eleme pedig "eper"
-ről "narancs"
-ra. Az elem listához való hozzárendelését indexelt értékadásnak nevezzük. Az indexelt értékadás nem működik a sztringek esetében:
1 2 sajat_sztring = "ADAT" sajat_sztring[3] = "G"Traceback (most recent call last): File "<input>", line 1, in <module> TypeError: 'str' object does not support item assignment
de a listák esetében igen:
1 2 3 sajat_lista = ["A", "D", "A", "T"] sajat_lista[3] = "G" print(sajat_lista)['A', 'D', 'A', 'G']
A szeletelő operátor használatával módosíthatjuk a teljes részlistát:
1 2 3 a_list = ["a", "b", "c", "d", "e", "f"] a_list[1:3] = ["x", "y"] print(a_list)['a', 'x', 'y', 'd', 'e', 'f']
Az elemeket a listából eltávolíthatjuk úgy, hogy hozzárendelünk egy üres listát:
1 2 3 a_list = ["a", "b", "c", "d", "e", "f"] a_list[1:3] = [] print(a_list)['a', 'd', 'e', 'f']
Hozzáadhatunk a listához elemeket úgy, hogy beszúrjuk őket egy üres szeletre a kívánt helyen:
1 2 3 a_list = ["a", "d", "f"] a_list[1:1] = ["b", "c"] print(a_list)['a', 'b', 'c', 'd', 'f']
1 2 a_list[4:4] = ["e"] print(a_list)['a', 'b', 'c', 'd', 'e', 'f']
11.8. Lista törlése¶
A szeletek használata a lista törlésére hibát adhat. A Python egy jobban olvasható alternatívát is kínál. A del
utasítás eltávolít egy elemet a listából:
1 2 3 a = ["egy", "kettő", "három"] del a[1] print(a)['egy', 'három']
A del
utasítás futási idejű hibát ad vissza, amennyiben az index kívül esik a tartományon.
A del
-t használhatjuk egy szelettel, hogy kitöröljünk egy részlistát:
1 2 3 a_list = ["a", "b", "c", "d", "e", "f"] del a_list[1:5] print(a_list)['a', 'f']
A szokásos módon a szelet által választott részlista tartalmazza az összes elemet az első indextől kezdődően, de már nem tartalmazza a második indexű elemet.
11.9. Objektumok és hivatkozások¶
Miután végrehajtjuk az értékadó utasításokat:
1 2 a = "banán" b = "banán"
látjuk, hogy az a
és b
a "banán"
sztring objektumra utal. De még nem tudjuk, hogy ugyanarra a sztring objektumra mutatnak-e.
Két lehetséges módja van annak, hogy a Python kezelje a memóriát:
Az első esetben a
és b
két különböző objektumra hivatkozik, amelyek azonos értékűek. A második esetben ugyanarra az objektumra hivatkoznak.
Az is
operátor segítségével megvizsgálhatjuk, hogy a két név ugyanarra az objektumra hivatkozik-e:
1 print(a is b)True
Azt mutatja, hogy az a
és b
ugyanarra az objektumra hivatkozik, továbbá, hogy a második a két pillanatnyi állapot közül az, amely pontosan leírja a kapcsolatot.
Mivel a sztringek megváltoztathatatlanok, a Python úgy optimalizálja az erőforrásokat, hogy létrehoz két nevet, amely ugyanarra a sztringre, ugyanarra az objektumra hivatkozik.
Ez nem áll fenn a listák esetében:
1 2 3 4 a = [1, 2, 3] b = [1, 2, 3] print(a == b) print(a is b)True False
Az aktuális állapot a következőképpen néz ki:
a
és b
-nek ugyanaz az értéke, de nem ugyanarra az objektumra hivatkoznak.
11.10. Fedőnevek¶
Mivel a változók objektumokra hivatkoznak, ha egy változót hozzárendelünk egy másikhoz, mindkét változó ugyanarra az objektumra fog hivatkozni:
1 2 3 a = [1, 2, 3] b = a print(a is b)True
Ebben az esetben a pillanatnyi állapot a következőképpen néz ki:
Mivel ugyanazon a listára két különböző névvel hivatkozunk, a
-val és b
-vel, azt mondjuk, hogy ők fedőnevek. A fedőneveken végrehajtott változtatások hatással vannak egymásra.
1 2 b[0] = 5 print(a)[5, 2, 3]
Habár ez a tulajdonság hasznos, néha kiszámíthatatlan és nemkívánatos. Általában biztonságosabb elkerülni a fedőnevek használatát, amikor módosítható objektumokkal dolgozunk (például: a tankönyvünk ezen pontján lévő felsorolások, továbbá több módosítható objektummal is fogunk találkozni, osztályokkal és objektumokkal, szótárakkal és halmazokkal). Természetesen a megváltozhatatlan objektumok (például: sztringek, rendezett n-esek) esetén nincs probléma – tehát a fedőneveket nem lehetséges csak úgy megváltoztatni. Ezért a Python szabadon ad fedőnevet a sztringeknek (és bármilyen más megváltozhatatlan adat típusoknak), amikor lehetőséget lát a takarékoskodásra.
11.11. Listák klónozása¶
Ha módosítani szeretnénk egy listát, és az eredeti példányát is meg szeretnénk őrizni, szükséges egy másolatot készíteni a listáról, nem csak a hivatkozásról. Ezt a folyamatot klónozásnak nevezzük, hogy elkerüljük a másolás szó kétértelműségét.
A lista klónozásának legegyszerűbb módja a szelet operátor használata:
1 2 3 a = [1, 2, 3] b = a[:] print(b)[1, 2, 3]
Az a
bármelyik szeletével egy új listát hozhatunk létre. Ebben az esetben a szelet tartalmazza a teljes listát. Tehát most a kapcsolat a következőképpen néz ki:
Most szabadon megváltoztathatjuk b
-t anélkül, hogy aggódnánk attól, hogy véletlenül megváltoztatjuk az a
-t:
1 2 b[0] = 5 print(a)[1, 2, 3]
11.12. Listák és a for
ciklus¶
A for
ciklus működik a listákkal is, ahogyan már korábban láthattuk. A for
ciklus általánosított szintaxisa:
for VÁLTOZÓ in LISTA: TÖRZS
Tehát, ahogy láttuk:
1 2 3 baratok = ["Péter", "Zoli", "Kata", "Zsuzsa", "Tamás", "József", "Sándor"] for barat in baratok: print(barat)
Bármely lista kifejezés használható egy for
ciklusban:
1 2 3 4 5 6 for szam in range(20): if szam % 3 == 0: print(szam) for filmek in ["vígjáték", "animációs", "romantikus"]: print("Én szeretem a " + filmek + "et!")
Az első példa kiírja a 3
szám összes többszörösét 0
és 19
között.
A második példa a különféle filmek iránti rajongást fejezi ki.
Mivel a listák módosíthatók, gyakran a listát szeretnénk bejárni, megváltoztatva minden elemét.
A következő példában az xs
lista összes elemét négyzetre emeljük:
1 2 3 4 xs = [1, 2, 3, 4, 5] for i in range(len(xs)): xs[i] = xs[i]**2
Vessünk egy pillantást a range(len(xs))
utasításra, amíg meg nem értjük, hogy működik!
Ebben a példában mind az elem értéke
(négyzetre akarjuk emelni az értékeket), mind pedig az indexe
(az új értéket hozzárendeljük a pozícióhoz) érdekel bennünket.
Ez a minta elég gyakori, a Python szebb módot ajánl ennek megvalósítására.
1 2 3 4 xs = [1, 2, 3, 4, 5] for (i, ert) in enumerate(xs): xs[i] = ert**2
Az enumerate
(index, érték) párokat generál a lista bejárás során. Próbáld ki a következő példát, hogy jobban megértsd az enumerate
működését!
1 2 for (i, v) in enumerate(["banán", "alma", "körte", "citrom"]): print(i, v)0 banán 1 alma 2 körte 3 citrom
11.13. Lista paraméterek¶
Ha egy listát argumentumként átadunk, akkor hivatkozni fog a listára, nem egy másolatot vagy klónt készít a listáról. Tehát a paraméterátadásra egy fedőnevet hoz létre: a hívónak van egy változója, mely a listára hivatkozik, és a hívott függvénynek van egy fedőneve, de alapvetően csak egy lista objektum van. Például az alábbi függvény argumentuma egy lista, mely a listának minden elemét megszorozza 2-vel:
1 2 3 4 def megduplaz(a_list): """ Átírjuk a lista minden elemét a kétszeresére. """ for (idx, ert) in enumerate(a_list): a_list[idx] = 2 * ert
Ha a szkripthez hozzáadjuk a következőket:
1 2 3 b_list = [2, 5, 9] megduplaz(b_list) print(b_list)
Amikor futtatjuk a következő eredményt kapjuk:
[4, 10, 18]
A fenti függvényben az a_list
paraméter és a b_list
változó ugyanazon objektum fedőnevei. Tehát a listában szereplő elemek módosítása előtt a lista állapota a következőképpen néz ki:
Mivel a lista objektum meg van osztva két keretre, a listát ezek közé írtuk. Ha egy függvény módosítja a lista paramétereinek elemeit, akkor a hívó látja a módosítást.
Használjuk a Python megjelenítőt!
A Python megjelenítő egy nagyon hasznos eszköz, mely segítséget nyújt a hivatkozások, fedőnevek, értékadások és a függvény argumentumok átadásának megértéséhez. Különös figyelmet kell fordítani azokra az esetekre, amikor egy listát klónozunk vagy két külön listánk van, valamint amikor csak egy alapvető lista szerepel, de egynél több fedőneves változó hivatkozik a listára.
11.14. Lista metódusok¶
A pont
operátor is használható a lista objektumok beépített metódusainak elérésére.
Kezdjük a leghasznosabb metódussal, amellyel hozzáadhatunk valamit a lista végéhez:
1 2 3 4 5 6 sajat_lista = [] sajat_lista.append(5) sajat_lista.append(27) sajat_lista.append(3) sajat_lista.append(12) print(sajat_lista)[5, 27, 3, 12]
Az append
lista metódus hozzáfűzi a megadott argumentumot a lista végéhez. Gyakran használjuk új lista készítésénél. A következő példával bemutatjuk néhány további lista metódus használatát.
Szúrjuk be a 12-t az 1-es pozícióra, eltolva a többi elemet!
1 2 sajat_lista.insert(1, 12) print(sajat_lista)[5, 12, 27, 3, 12]
Hány 12-es érték szerepel a listában?
1 print(sajat_lista.count(12))2
Szúrjuk be a teljes listát a sajat_lista végére!
1 2 sajat_lista.extend([5, 9, 5, 11]) print(sajat_lista)[5, 12, 27, 3, 12, 5, 9, 5, 11]
Keressük meg az első 9-es érték indexét a listában!
1 print(sajat_lista.index(9))6
Fordítsuk meg a listát!
1 2 sajat_lista.reverse() print(sajat_lista)[11, 5, 9, 5, 12, 3, 27, 12, 5]
Rendezzük a listát!
1 2 sajat_lista.sort() print(sajat_lista)[3, 5, 5, 5, 9, 11, 12, 12, 27]
Rendezzünk egy szöveges adatokat tartalmazó listát!
1 2 3 4 5 6 szoveg_lista = ["barack", "alma", "mandarin"] szoveg_lista.sort() print(szoveg_lista) szoveg_lista2 = ["én", "te", "ő", "mi", "ti", 'ők'] szoveg_lista2.sort() print(szoveg_lista2)['alma', 'barack', 'mandarin'] ['mi', 'te', 'ti', 'én', 'ő', 'ők']
A második listára kapott eredménnyel valószínűleg nem vagyunk elégedettek. Mivel a rendezés az elemek összehasonlításán alapul, ezért azt kell megoldanunk, hogy a hasonlítás az általunk kívánt módon történjen meg:
1 2 3 4 5 6 7 import locale import functools locale.setlocale(locale.LC_ALL, "HU_hu.UTF8") # a nyelv és a kódolás beállítása szoveg_lista2 = ["én", "te", "ő", "mi", "ti", 'ők'] szoveg_lista2.sort(key = functools.cmp_to_key(locale.strcoll)) print(szoveg_lista2)
A korábbiakban a sort
metódust paraméter nélkül használtuk. Most a key
paraméter segítségével megadjuk, hogy az strcoll
hasonlítsa össze az elemeket, mely figyelembe veszi a 4. sorban beállított környezetet. Most már nem okoznak problémát az ékezetes karakterek.
['én', 'mi', 'ő', 'ők', 'te', 'ti']
Távolítsuk el az első 12-es értéket a listából!
1 2 sajat_lista.remove(12) print(sajat_lista)[3, 5, 5, 5, 9, 11, 12, 27]
Kísérletezz és játssz az itt bemutatott lista metódusokkal, és olvasd el a rájuk vonatkozó dokumentációkat, addig, amíg nem vagy biztos benne, hogy megértetted hogyan működnek.
11.15. Tiszta függvények és módosítók¶
Azok a függvények, amelyek argumentumként egy listát kapnak, és módosítják a listát a végrehajtás során módosítónak, és az általuk végrehajtott változtatásokat pedig mellékhatásnak nevezzük.
A tiszta függvény nem eredményez mellékhatásokat. A tiszta függvény a hívó programmal csak a paramétereken keresztül kommunikál, amelyeket nem módosít, és visszaad egy értéket. Itt a megduplaz
egy tiszta függvényként van megírva:
1 2 3 4 5 6 7 8 def megduplaz(a_list): """ Visszaad egy listát, mely az a_list elemeinek kétszeresét tartalmazza. """ uj_list = [] for ertek in a_list: uj_elem = 2 * ertek uj_list.append(uj_elem) return uj_list
Ez a megduplaz
változat nem változtatja meg a függvény argumentumait:
1 2 3 4 b_list = [2, 5, 9] xs = megduplaz(b_list) print(b_list) print(xs)[2, 5, 9] [4, 10, 18]
Egy korábbi szabály szerint, amely az értékadásra vonatkozott „először kiértékeljük a jobb oldalt, majd hozzárendeljük az eredményt a változóhoz”. Tehát elég biztonságos a függvény eredményét ugyanahhoz a változóhoz rendelni, melyet átadtunk a függvénynek:
1 2 3 b_list = [2, 5, 9] b_list = megduplaz(b_list) print(b_list)[4, 10, 18]
Melyik stílus a jobb?
Bármi, amit a módosítókkal meg lehet tenni az tiszta függvényekkel is elvégezhető. Valójában egyes programozási nyelvek csak tiszta függvényeket engedélyeznek. Van néhány bizonyíték arra, hogy azok a programok, melyek tiszta függvényeket használnak gyorsabbak, és kevesebb hibalehetőséget tartalmaznak, mint a módosítókat használók. Mindazonáltal a módosítók néha kényelmesek, és egyes esetekben a funkcionális programok kevésbé hatékonyak.
Általánosságban azt javasolják, hogy tiszta függvényeket írjunk, és csak akkor alkalmazzuk a módosítókat, ha nyomós okunk van rá, és előnyünk származik belőle. Ezt a megközelítést funkcionális programozási stílusnak nevezzük.
11.16. Listákat előállító függvények¶
A fent említett megduplaz
tiszta verziója egy fontos mintát használ az eszköztárából. Amikor egy listát létrehozó és visszaadó függvényt kell írni, a minta általában:
1 2 3 4 5 inicializálja az eredmény változót, legyen egy üres lista ciklus hozzon létre egy új elemet fűzze hozzá az eredményhez return eredmény
Mutassuk be egy másik használati módját ennek a mintának! Tegyük fel, hogy már van egy primszam(x)
függvényünk, amely teszteli, hogy az x
prímszám-e. Írj egy függvényt, amely visszaadja az összes n
-nél kisebb prímszámot:
1 2 3 4 5 6 7 def prim_kisebbmint(n): """ Visszaadja az összes n-nél kisebb prímszámot. """ eredmeny = [] for i in range(2, n): if primszam(i): eredmeny.append(i) return eredmeny
11.17. Szrtingek és listák¶
A két leghasznosabb metódus a sztringek esetében a részsztringek listájának (oda és vissza) konverziója. A split
metódus (melyet már korábban láthattunk) szétválasztja a sztringet szavak listájába. Alapértelmezés szerint bármilyen számú whitespace karakter tekinthető szóhatárnak:
1 2 3 nota = "Esik eső, szép csendesen csepereg..." szavak = nota.split() print(szavak)['Esik', 'eső,', 'szép', 'csendesen', 'csepereg...']
Az opcionálisként megadott argumentumot határolónak nevezzük, amely meghatározza, hogy mely karakterlánc legyen a határ a részsztringek között. A következő példában az se
sztring határolót használjuk:
1 print(nota.split("se"))['Esik eső, szép c', 'nde', 'n c', 'pereg...']
Figyeljük meg, hogy a határoló nem jelenik meg az eredményben.
A split
metódus inverze a join
metódus. Kiválaszthatjuk a kívánt határoló sztringet (gyakran ragasztónak nevezik), és összefűzhetjük a lista minden egyes elemét a ragasztóval.
1 2 3 ragaszto = ";" s = ragaszto.join(szavak) print(s)'Esik;eső,;szép;csendesen;csepereg...'
Az összeillesztett lista (a példában szereplő szavak
) nem módosul. Továbbá, amint ez a következő példa is mutatja, használhatunk üres vagy több karakterből álló sztringet ragasztóként:
1 print(" -- ".join(szavak))'Esik -- eső, -- szép -- csendesen -- csepereg...'
1 print("".join(szavak))'Esikeső,szépcsendesencsepereg...'
11.18. A list és a range¶
A Python egy list
nevezetű beépített konverziós függvénnyel rendelkezik, amely megpróbál bármit listává alakítani.
1 2 3 xs = list("Mocsári Béka") print(xs) print("".join(xs))['M', 'o', 'c', 's', 'á', 'r', 'i', ' ', 'B', 'é', 'k', 'a'] 'Mocsári Béka'
A range
egyik tulajdonsága az, hogy nem számolja ki rögtön az összes értéket: „félre teszi” a számolást, és csak kérésre végzi el, azaz „lustán”. Mondhatni ígéretet ad rá, hogy amikor szükségünk lesz egy elemre, akkor elő fogja azt állítani. Ez nagyon kényelmes, ha a számításunk rövidzáras keresés, és korábban visszatér az értékkel, mint a következő esetben:
1 2 3 4 5 6 7 8 def f(n): """ Keresse meg az első pozitív egész számot 101 és n között, amely osztható 21-el. """ for i in range(101, n): if (i % 21 == 0): return i teszt(f(110) == 105) teszt(f(1000000000) == 105)
A második teszt-ben, ha a range
fel lenne töltve a lista összes elemével, gyorsan kihasználná a számítógép memóriáját, és a program összeomlana. De ennél okosabb! Ez a számítás jól működik, mert a range
objektum csak ígéret ad az elemek előállítására, amikor szükséges. Amint a ha
feltétel igazzá válik, nem generál további elemeket, és a függvény visszatér. (Megjegyzés: A Python 3 előtt a range
nem volt lusta. Ha a Phython korábbi verzióját használja, YMMV!)
YMMV: Your Mileage May Vary (A kilométer teljesítményed változhat)
A YMMV rövidítés azt jelenti, hogy a kilométer teljesítményed változhat. Az amerikai autós hirdetések gyakran megemlítették az autók üzemanyag-felhasználási adatait, például, hogy az autó gallonként 28 mérföldet tehet meg. De ezt mindig egy apró-betűs jogi résznek kell kísérnie, figyelmeztetve az olvasót, hogy lehet nem fognak ugyanannyit kapni. Az YMMV kifejezést a köznyelvben úgy használjuk, hogy „az eredmények eltérhetnek”, például A telefon akkumulátorának élettartama 3 nap, de YMMV.
Néha találkozhattuk a lusta range
-el, amely egy list
hívásába van beágyazva. Ez arra kényszeríti Pythont, hogy a lusta ígéretét egy listává változtassa:
1 2 print(range(10)) # Hozzon létre egy lusta ígéretet print(list(range(10))) # Hívja meg az ígéretet, mely létrehozza a listát
Az eredmény a következő:
range(0, 10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
11.19. Beágyazott listák¶
A beágyazott lista olyan lista, amely egy másik listában elemként jelenik meg. Ebben a listában a 3. indexű elem egy beágyazott lista:
1 beagyazott = ["hello", 2.0, 5, [10, 20]]
Ha a lista 3. elemét kiírjuk a következőt kapjuk:
1 print(beagyazott[3])[10, 20]
Ha a beágyazott listának egy elemét ki akarjuk íratni, ezt két lépésben tehetjük meg:
1 2 elem = beagyazott[3] print(elem[0])10
Vagy kombinálhatjuk őket:
1 print(beagyazott[3][1])20
A zárójel operátor kiértékelése balról jobbra történik, tehát a kifejezés megkapja a beagyazott
lista 3. elemének első elemét.
11.20. Mátrixok¶
A beágyazott listákat gyakran használják a mátrixok ábrázolásánál. Például legyen a következő mátrix:
amit ábrázolni lehet, mint:
1 mx = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
mx
egy három elemű lista, mely mindegyik eleme a mátrix egy sora.
A mátrixból egy teljes sort kiválaszthatunk a szokásos módon:
1 print(mx[1])[4, 5, 6]
Vagy kiválaszthatunk egy elemet a mátrixból,a kettős-indexet használva:
1 print(mx[1][2])6
Az első index kiválasztja a sort, a második pedig az oszlopot. Habár a mátrixok ábrázolásának ezen módja a gyakoribb, ez nem az egyetlen lehetőség. Kevesebb változatot használhatunk az oszlopok listájára, mint a sorokra. Később további radiálisabb alternatívát fogunk látni a szótár használatával.
11.21. Szójegyzék¶
- beágyazott lista (nested list)
- Egy lista, amelynek egy eleme egy másik lista.
- elem (element, item)
- Egy érték a listából. A szögletes zárójel operátor segítségével választjuk ki az elemet a listából.
- fedőnevek (aliases)
- Több változó, amelyek ugyanazon objektumra hivatkoznak.
- határoló (delimiter)
- Olyan karakter vagy karakterlánc, amely jelzi, hol kell szétválasztani egy sztringet.
- index (index)
- Egy egész szám, amely jelöli egy elem listán belüli pozícióját. Az indexek 0-tól kezdődnek.
- ígéret (promise)
- Egy olyan objektum, amely megígéri, hogy valamilyen munkát elvégez vagy valamilyen értéket kiszámol, ha szükség van rá, de lustán végzi el a munkát (nem azonnal). A
range
hívása ígéretet eredményez. - klónozás (clone)
- Új objektum létrehozása, melynek ugyanaz az értéke, mint egy meglévő objektumnak. Egy objektumra mutató hivatkozás másolása fedőnevet hoz létre, de nem klónozza az objektumot.
- lépésköz (step size)
- A lineáris sorozatban az egymást követő elemek közötti intervallum. A
range
függvénynek a harmadik (és opcionális) argumentumát lépés méretnek nevezzük. Ha nincs megadva, az alapértelmezett értéke 1. - lista (list)
- Értékek gyűjteménye. Mindegyik értéknek meghatározott helye van a listában. Más típusokhoz hasonlóan
str
,int
,float
, stb. van egylist
típus-átalakító függvény is, amely bármely argumentumát listává próbálja alakítani. - lista bejárás (list traversal)
- A lista minden egyes elemének sorrendben történő elérése.
- mellékhatás (side effect)
- Egy program állapotának megváltoztatása a hívó függvény által. A mellékhatásokat csak módosítókkal lehet előállítani.
- minta (pattern)
- Utasítások sorozata vagy olyan kódolási stílus, amely általánosan alkalmazható számos különböző helyzetben. Érett informatikussá válik az, aki megtanulja, létrehozza az eszközkészletet alkotó mintákat és algoritmusokat. A minták gyakran megfelelnek a mentális blokkosításnak.
- módosítható adat típusok (mutable data value)
- Olyan adat értékek, amelyek módosíthatók. Minden módosítható értéktípus összetett. A listák és szótárak módosíthatók, a sztringek és a rendezett n-esek nem.
- módosító (modifier)
- Olyan függvény, amely megváltoztatja az argumentumokat a függvény törzsében. Csak a módosítható típusok változtathatók meg.
- objektum (object)
- Egy „dolog”, amelyre egy változó hivatkozhat.
- sorozat (sequence)
- Bármilyen olyan adat típus, mely rendezett elemeket tartalmaz, és minden elemet egy index-el azonosítunk.
- tiszta függvény (pure function)
- Olyan függvény, mely nem okoz mellékhatásokat. A tiszta függvények csak a visszatérítési értékekkel okozhatnak változást a hívó függvényben.
- változtathatatlan adat érték (immutable data value)
- Olyan adatérték, amelyet nem lehet módosítani. Az értékadások a megváltoztathatatlan elemek vagy szeletek esetén futási idejű hibát okoznak.
11.22. Feladatok¶
Mi lesz a Python kód eredménye a következő utasítás esetén?
list(range(10, 0, -2))
A
range
függvény három argumentuma a start, stop és step. Ebben a példában astart
nagyobb, mint astop
. Mi történik, ha astart < stop
és astep < 0
? Írj egy szabályt astart
, astop
és astep
közötti kapcsolatokra.Tekintsük a következő kódrészletet:
1 2 3 4 5
import turtle Eszti = turtle.Turtle() Sanyi = Eszti Sanyi.color("hotpink")
Ez a kódrészlet egy vagy két teknőc példányt hoz létre? A
Sanyi
színének megváltoztatásaEszti
színét is meg fogja változtatni? Magyarázd el részletesen!Rajzolj az
a
ésb
számára egy pillanatképet, a következő Python kód3.
sorának végrehajtása előtti és utáni állapotában:1 2 3
a = [1, 2, 3] b = a[:] b[0] = 5
Mi lesz a következő programrészlet kimenete?
1 2 3 4 5
ez = ["Én", "nem", "vagyok", "egy", "csodabogár"] az = ["Én", "nem", "vagyok", "egy", "csodabogár"] print("Test 1: {0}".format(ez is az)) ez = az print("Test 2: {0}".format(ez is az))
Adj részletes magyarázatot az eredményekről.
A listákat használhatjuk matematikai vektorok ábrázolására. Ebben és az ezt követő néhány gyakorlatban olyan függvényeket írunk le, amelyek végrehajtják a vektorok alapvető műveleteit. Hozz létre egy
vectorok.py
szkriptet, és írd bele az alábbi Python kódot, hogy mindegyiket letesztelhesd!Írj egy
vektorok_osszege(u, v)
függvényt, amely paraméterként két azonos hosszúságú listát kap, és adjon vissza egy új listát, mely tartalmazza a megfelelő elemek összegét:1 2 3
teszt(vektorok_osszege([1, 1], [1, 1]) == [2, 2]) teszt(vektorok_osszege([1, 2], [1, 4]) == [2, 6]) teszt(vektorok_osszege([1, 2, 1], [1, 4, 3]) == [2, 6, 4])
Írj egy
szorzas_skalarral(s, v)
függvényt, amely paraméterként egys
számot, és egyv
listát kap, és visszatér a függvény av
listas
skalárral való szorzatával.1 2 3
teszt(szorzas_skalarral(5, [1, 2]) == [5, 10]) teszt(szorzas_skalarral(3, [1, 0, -1]) == [3, 0, -3]) teszt(szorzas_skalarral(7, [3, 0, 5, 11, 2]) == [21, 0, 35, 77, 14])
Írj egy
skalaris_szorzat(u, v)
függvényt, amely paraméterként megkap két azonos hosszúságú számokat tartalmazó listát, és visszaadja a megfelelő elemek skaláris szorzatát.1 2 3
teszt(skalaris_szorzat([1, 1], [1, 1]) == 2) teszt(skalaris_szorzat([1, 2], [1, 4]) == 9) teszt(skalaris_szorzat([1, 2, 1], [1, 4, 3]) == 12)
Extra matematikai kihívások: Írj egy
vektorialis_szorzat(u, v)
függvényt, amely paraméterként megkap két 3 hosszúságú számokból álló listát, és visszatér a vektoriális szorzatukkal. Írd meg a saját tesztjeid!Írd le a
" ".join(nota.split())
ésnota
közötti kapcsolatot az alábbi kódrészletben. Ugyanazok a sztringek vannak hozzárendelve anota
-hoz? Mikor lennének különbözőek?1
nota = "Esik eső, szép csendesen csepereg..."
Írj egy
cserel(s, regi, uj)
függvényt, amely kicseréli aregi
összes előfordulását auj
-ra azs
szrtingben.1 2 3 4 5 6 7 8
teszt(cserel("Mississippi", "i", "I") == "MIssIssIppI") s = "Kerek a gömb, gömbszerű!" teszt(cserel(s, "öm", "om") == "Kerek a gomb, gombszerű!") teszt(cserel(s, "o", "ö") == "Kerek a gömb, gömbszerű!")
Tipp: Használd a
split
ésjoin
metódusokat.Tegyük fel, hogy két változó értékét akarjuk felcserélni. Újra felhasználható függvényt hozz létre, írd bele az alábbi kódot:
1 2 3 4 5 6 7 8 9 10
def csere(x, y): # Hibás változat print("csere utasítás előtt: x:", x, "y:", y) (x, y) = (y, x) print("csere utasítás után: x:", x, "y:", y) a = ["Ez", "nagyon", "érdekes"] b = [2,3,4] print("csere függvény hívása előtt: a:", a, "b:", b) csere(a, b) print("csere függvény hívása után: a:", a, "b:", b)
Futtasd a fenti programot, és írd le az eredményeket. Hoppá! Nem azt tette, amit szerettünk volna! Magyarázd el miért nem. Használd a Python megjelenítőt, amely segítségével építs egy működő koncepcionális modellt! Mi lesz az
a
ésb
értéke acsere
függvény hívása után?