Kurzusok
/
Python
Python
/
Feladatok
/
Repülőjegyek
Repülőjegyek

Repülőjegyek

Tanulófeladat

Bevezetés

A generator egy olyan függvény vagy kifejezés, amely egy különleges típusú iterátort ad vissza, amelyet generator iterator-nak nevezünk. A Generator-iterator-ok lusta iterátorok: nem tárolják az values-üket a memóriában, hanem generálják az értékeiket, amikor szükség van rájuk.

Egy generátorfüggvény úgy néz ki, mint bármelyik másik függvény, de tartalmaz egy vagy több yield kifejezést. Minden yield felfüggeszti a kód végrehajtását, és elmenti az aktuális végrehajtási állapotot (beleértve az összes lokális változót és a try-utasításokat). Amikor a generátor folytatódik, onnan veszi fel az állapotot, ahol felfüggesztődött, ellentétben a hagyományos függvényekkel, amelyek minden híváskor visszaállnak az elejére.

Generátor létrehozása

A generátorokat nagyon hasonlóan hozzuk létre, mint a többi ciklusos vagy rekurzív függvényt, de szükség van hozzájuk egy yield kifejezésre, amelyet kicsit később részletesen meg is nézünk.

Példa erre egy olyan függvény, amely egy adott számlistából visszaadja a négyzeteket. Ahogy most meg van írva, az összes bemenetet fel kell dolgozni, mielőtt bármilyen értéket vissza lehetne adni:

>>> def squares(list_of_numbers):
...     squares = []
...     for number in list_of_numbers:
...         squares.append(number ** 2)
...     return squares

Ezt a függvényt így alakíthatod át generátorrá:

>>> def squares_generator(list_of_numbers):
...     for number in list_of_numbers:
...         yield number ** 2

Ennek az az értelme, hogy akkor használsz generátort, amikor nem kell az összes értéket egyszerre előállítanod. Ez memóriát és számítási kapacitást takarít meg, hiszen csak az az érték számítódik ki, amelyen éppen dolgozol.

Generátor használata

A generátorok a Pythonban a legtöbb iterables helyett használhatók. Ez magában foglalja azokat a függvényeket vagy objektumokat, amelyek iterable/iterator argumentumot várnak.

A squares_generator() generátor használatához:

>>> squared_numbers = squares_generator([1, 2, 3, 4])

>>> for square in squared_numbers:
...     print(square)
...
1
4
9
16

A generator belsejében lévő értékeket a next() függvénnyel is előállíthatod, illetve elérheted. A next() meghívja egy generátoriterátor-objektum __next__() metódusát, „előrehaladva” vagy kiértékelve a kódot egészen a yield kifejezéséig, amely aztán „kiszolgáltat”, azaz visszaad egy értéket:

>>> squared_numbers = squares_generator([1, 2])

>>> next(squared_numbers)
1
>>> next(squared_numbers)
4

Amikor egy generator-iterator-t teljesen felhasználtál, és nincs több visszaadható értéke, akkor StopIteration hibát dob.

>>> next(squared_numbers)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
Note

A generátoriterátorok az iterátorok egy különleges részhalmazát alkotják. Az Iterators az a mechanizmus/protokoll, amely lehetővé teszi az iterables feletti végigiterálást. A generátoriterátorok és a gyakori Python-iterables által visszaadott iterátorok nagyon hasonlóan viselkednek, de van néhány fontos különbség, amire érdemes figyelni:

  • Lazán értékelődnek ki; az iteráció egyirányú, és nincs „visszalépés” egy korábbi értékre.
  • A visszaadott értékeken végigiterálva felhasználódnak; nincs visszaállítás és nincs mentés a memóriában.
  • Nem rendezhetők és nem fordíthatók meg.
  • Nem sorozattípusok, és nincs bennük indexes. Nem hivatkozhatsz egy korábbi vagy későbbi értékre összeadással vagy kivonással, és nem használhatod a szögletes zárójeles ([]) jelölést vagy a szeletelést.
  • Nem használhatók a len() függvénnyel, mivel nincs hosszuk.
  • Lehetnek végesek vagy végtelenek; légy óvatos, amikor egy végtelen generator-iterator összes értékét próbálod összegyűjteni!

A yield kifejezés

A yield kifejezés nagyon hasonlít a return kifejezéshez. A return kifejezéssel ellentétben a yield egy adott ponton adja át az értékeket a hívónak, és felfüggeszti a további értékek kiértékelését/visszaadását egészen addig, amíg azokat nem kérik. Amikor a yield kiértékelődik, szünetelteti a körülvevő függvény végrehajtását, és visszaadja a függvény értékeit abban az adott pillanatban. A függvény ezután scope-ban marad, és amikor meghívják a __next__()-et, a végrehajtás folytatódik, amíg újra nem találkozik egy yield-del.

Note

A yield kifejezések használata függvényeken kívül tilos.

>>> def infinite_sequence():
...     current_number = 0
...     while True:
...         yield current_number
...         current_number += 1

>>> lets_try = infinite_sequence()
>>> lets_try.__next__()
0
>>> lets_try.__next__()
1

Miért hozzunk létre generátort?

A generátorok sok helyen hasznosak.

Amikor egy potenciálisan nagy értékgyűjteménnyel dolgozol, lehet, hogy nem akarod az összeset a memóriába tenni. Egy generátorral darabonként dolgozhatsz fel nagyobb adathalmazokat, ami memóriát takarít meg és javítja a teljesítményt.

A generátorok akkor is nagyon hasznosak, ha egy folyamat vagy számítás összetett, költséges vagy végtelen:

>>> def infinite_sequence():
...     current_number = 0
...     while True:
...         yield current_number
...         current_number += 1

Mostantól, valahányszor meghívják a __next__()-et az infinite_sequence objektumon, az a korábbi szám + 1 értéket adja vissza.

Utasítások

A Conda Airlines a programozás világának legnagyobb légitársasága, amely naponta több mint 10 000 járatot indít!

Jelenleg az összes ülést kézzel osztják ki az utasoknak, ezt automatizálni kell.

Felkértek téged, hogy készíts szoftvert az utasok üléskiosztásának automatizálására. Elvárják, hogy a szoftvered memóriatakarékos és nagy teljesítményű legyen.

1. Generálj ülésbetűket

A Conda ülésbetűket szeretne generálni a repülőgépeihez. Egy repülőgép üléssorokból áll. Minden sorban 4 ülés van. Egy sor ülései mindig A, B, C és D nevet kapják. A sor első ülése A, a második ülése B, és így tovább. Miután elérte a D-t, újra A-val kell kezdenie.

Készíts egy generate_seat_letters(<number>) függvényt, amely egy int értéket fogad, ami megmondja, hány ülésbetűt kell generálni. A függvény ezután az ülésbetűk egy iterálható sorozatát adja vissza.

>>> letters = generate_seat_letters(4)
>>> next(letters)
"A"
>>> next(letters)
"B"

2. Generálj üléseket

A Conda egy olyan rendszert szeretne, amely adott számú ülést tud generálni a repülőgépeihez. Minden repülőgépben 4 ülés van soronként. A sorokat számokkal jelöljük, 1-től indulva és felfelé haladva. Az ülések sorrendje ilyen legyen: 1A, 1B, 1C, 1D, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, ...

Íme egy példa:

x 1 2
Sor 5 21
Ülésbetű A D
Eredmény 5A 21D

Sok légitársaságnál az utasok babonája miatt nincs 13-as számú sor a járatokon. A Conda Airlines is követi ezt a hagyományt, ezért ügyelj rá, hogy ne generálj ülést a 13-as sorhoz.

Készíts egy generate_seats(<number>) függvényt, amely egy int értéket fogad, ami megmondja, hány ülést kell generálni. A függvény ezután a generált ülések egy iterálható sorozatát adja vissza.

>>> seats = generate_seats(10)
>>> next(seats)
"1A"
>>> next(seats)
"1B"

3. Rendelj üléseket az utasokhoz

Most, hogy van már egy függvényed az ülések generálására, azzal üléseket is kioszthatsz az utasoknak.

Készíts egy assign_seats(<passengers>) függvényt, amely egy utasneveket tartalmazó list-et fogad. A függvény ezután egy szótárat adjon vissza, amelyben a passenger a kulcs és a seat_number az érték.

>>> passengers = ['Jerimiah', 'Eric', 'Bethany', 'Byte', 'SqueekyBoots', 'Bob']

>>> assign_seats(passengers)
{'Jerimiah': '1A', 'Eric': '1B', 'Bethany': '1C', 'Byte': '1D', 'SqueekyBoots': '2A', 'Bob': '2B'}

4. Jegykódok

A Conda Airlines egyedi kódot szeretne minden jegyhez. Mivel nagy légitársaság, rengeteg járatuk van. Ez azt jelenti, hogy több járat is ugyanazzal az ülésszámmal közlekedik. Szeretnék, ha készítenél egy rendszert, amely egyedi jegyet állít elő, egy 12 karakter hosszú stringet.

A kód az assigned_seat értékkel kezdődik, ezt követi a flight_id. A kód többi részét 0s tölti ki.

Készíts egy generate_codes(<seat_numbers>, <flight_id>) függvényt, amely seat_numbers egy list-jét és a flightszámot tartalmazó string-et fogad. A függvény ezután egy generator-t adjon vissza, amely ticket_number értékeket ad.

>>> seat_numbers = ['1A', '17D']
>>> flight_id = 'CO1234'
>>> ticket_ids = generate_codes(seat_numbers, flight_id)

>>> next(ticket_ids)
'1ACO12340000'
>>> next(ticket_ids)
'17DCO1234000'
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Python Exercism

Készen állsz elkezdeni a(z) Repülőjegyek feladatot?

Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Python nyelvet 17 fogalom146 feladat segítségével, valódi emberi mentorálással, mindez ingyen.