Jose: Hallo allemaal, welkom terug
en in deze video hebben we het over generatoren in Python.
Ik ben erg enthousiast
over deze sectie omdat we het gaan hebben
over wat meer geavanceerde dingen en generatoren
zijn een van deze onderwerpen
in Python die veel cursussen niet eens noemen, maar ze zijn
essentieel voor de prestaties en ook omdat de e -sync-ontwikkeling
in Python,
de e-synchrone ontwikkeling
die we later zullen leren, is gebaseerd op deze generatoren.
Als je generatoren
begrijpt, worden veel dingen in Python een stuk duidelijker.
Dus wat is een generator?
Een generator in Python is een functie.
Het is een bijzondere functie.
Zie een functie die de status onthoudt waarin
deze zich tussen uitvoeringen
bevindt, zodat u de functie meerdere keren
kunt uitvoeren en onthoudt wat hij
deed de laatste keer dat u hem uitvoerde.
Dus dat klinkt best raar, ik zal het uitleggen met een voorbeeld.
Stel je voor dat je een lijst
van 100 getallen
wilt maken, heel eenvoudig, je wilt een nieuwe lijst krijgen met getallen
van nul tot 99, 100 niet meegerekend.
Dus je zou een functie als deze kunnen maken.
Het is duidelijk dat je geen bereik gebruikt, enzovoort, je kent het bereik.
Laten we geen bereik gebruiken, laten we in plaats daarvan een lijst helemaal opnieuw opbouwen.
Hoe zou je het doen.
Een goede manier om dit te doen zou zijn om met een lege lijst te beginnen.
Laten we zeggen noem het nums en maak het gelijk aan een lege lijst.
En begin ook met een index gelijk aan nul.
Terwijl i kleiner is dan
100, zeg nums dot append i.
Dus je gaat nul toevoegen aan het begin.
Dan ga je i met één verhogen, waardoor
het er één wordt.
Je gaat er één toevoegen, herhalen,
twee toevoegen, dan drie enzovoort, totdat je bij 99 bent.
En aan het einde van
deze functie retourneert u nums, uw lijst met getallen.
Als we honderd getallen afdrukken en dat uitvoeren.
We kunnen zien dat
het hier onze lijst van honderd nummers bevat.
Natuurlijk kunnen we hiervoor lijstbegrip gebruiken.
We zouden de bereikfunctie
kunnen gebruiken, maar laten we voor nu
aannemen dat dit een coole manier is om het te
doen, want wat ik echt uitleg, is in wezen hoe de bereikfunctie aan de binnenkant werkt.
Dus we construeren een
lijst, vullen deze met de eerste honderd getallen en keren dan terug.
Nu hebben we honderd nummers in een lijst.
Deze volledige lijst is in het geheugen van uw computer opgeslagen
als deze retourwaarde van de functie.
Nu is honderd nummers niet erg
groot, het is nogal een
kleine hoeveelheid ruimte, maar laten we zeggen dat we 10 miljoen
wilden opslaan, miljoen is zoiets als honderd
nummers, maar het zou zoiets zijn als een miljoen nummers.
Je zou een lijst van een miljoen getallen genereren
en deze opslaan in
deze variabele die in het geheugen van je
computer gaat en het is vermoedelijk een grotere hoeveelheid
geheugen die het in beslag neemt, omdat
elk van deze getallen een kleine hoeveelheid van je computergeheugen in beslag neemt.
Als je 10 miljoen nummers wilde, dan is het groter en zo.
Nu 10 miljoen nummers hebben is geen goed voorbeeld, maar stel je
voor dat je een hele lange lijst van iets hebt.
Deze worden bijvoorbeeld vaak gebruikt bij
het berekenen van priemgetallen en in big
data en dat soort
dingen, misschien wil je soms grote lijsten met dingen.
Dus een generator wordt gebruikt om dit probleem te
omzeilen, omdat de veronderstelling is dat je niet 100
nummers tegelijk nodig hebt.
Wat je nodig hebt is nul zodat je er iets mee kunt doen.
En dan eentje zodat je er iets mee kunt doen.
En dan nog twee zodat je er iets mee kunt doen.
Met deze honderd getallen zouden we
ze bijvoorbeeld allemaal met twee kunnen vermenigvuldigen en ze in een andere lijst kunnen opslaan.
Hoe zou je dat doen?
Je zou zoiets doen als minder begrip,
x keer twee voor x in honderd getallen.
Wat je hier doet, is dat je
deze lijst gebruikt om eroverheen te isoleren en elk getal met twee te vermenigvuldigen.
Laten we denken dat deze vermenigvuldiging
met twee een bewerking is die we
in deze getallen willen doen om iets te berekenen.
Een ander voorbeeld zou zijn, als u
veel gebruikers heeft en u wilt de betrokkenheid om hen
heen berekenen, of hoe betrokken ze zijn
bij uw systeem, of iets dergelijks.
In wezen wil je elk
element doornemen en een bewerking uitvoeren.
Het ding hier is dat je niet alle elementen tegelijk nodig hebt.
Je hebt ze een voor een nodig.
Dit is dus waar generatoren voor worden gebruikt.
In plaats van de volledige lijst met elementen
te hebben, geeft de generator u
het eerste element van de
lijst, zonder de hele lijst in het geheugen op te slaan.
De volgende keer dat u de
generator aanroept, onthoudt hij het element dat hij u het laatst
heeft gegeven, en weet hij u het tweede element te geven.
Dan voer je het opnieuw uit en het geeft je
het derde element, enzovoort.
Het slaat de lijst nooit op in
het geheugen, het onthoudt altijd alleen het laatste nummer dat het je
heeft gegeven, zodat het je het volgende kan geven.
Je moet de functie elke
keer leuk maken als je een nieuw getal wilt,
en daarom wordt het een generator genoemd, omdat het
getallen genereert, of inderdaad strings, of gebruikers of wat het ook is dat je wilt genereren.
Hier is hoe je het zou doen, in plaats van "nums. append(i)", zeg je "yield
i", want i is het getal dat we willen retourneren,
we hebben dit getal niet
langer nodig met gelijke vierkante haakjes, en
we hebben het return-segment ook niet langer nodig.
Dus nu wordt deze functie hier een generatorfunctie genoemd.
Opbrengst lijkt veel op teruggave, maar wat er gebeurt, is
dat je i krijgt als je het roept, en dan herinnert
het zich dat het hier is, het stopt vlak
voor regel vijf. Direct na lijn vier daar
in het midden.
De volgende keer dat je de functie aanroept, zal het
doorgaan, dus wat het zal doen is
het met één verhogen, het zal de lus opnieuw uitvoeren
en er één opleveren, je één geven en dan stoppen.
De volgende keer dat je
het roept, zal het blijven toenemen,
ik koop er een en herhaal de lus en geef je er twee, en dan stopt het, enzovoort.
Uiteindelijk, als je geen nummers
meer hebt, levert het niets op.
En dan weet je dat het klaar is.
Dus, hoe gaan we dit doen?
Laten we eerst honderd getallen uitprinten.
Merk op hoe het ons niet langer een
lijst geeft, nu geeft het ons een generatorobject,
dat honderd getallen wordt genoemd, dus de
naam van onze functie.
Het geeft ons ook het geheugenadres van ons object.
Merk op hoe we een functie hebben
gedefinieerd, maar de afdruk vertelt ons dat dit een
object is, omdat Python
op de achtergrond beseft dat je opbrengst
hebt gebruikt, je een generator maakt en die in een python-object verandert.
Ik zal je later vertellen hoe
je deze objecten zelf kunt maken zonder een functie.
Laten we onze generator dus opslaan in een variabele.
We gaan het "g" noemen, dat is
een vrij populaire naam voor een generator in een klein programma.
Als je veel generatoren hebt,
moet je natuurlijk voor een meer beschrijvende naam gaan.
Dan gaan we de volgende waarde afdrukken die
de generator ons zou geven.
Merk op dat wanneer je een generator initialiseert, hij
de functie niet uitvoert, hij begint helemaal bovenaan
zonder helemaal te draaien.
Wanneer u het om de volgende waarde vraagt, loopt het
op tot het rendement en
geeft het u de waarde die u heeft opgeleverd.
De manier waarop je het om de
volgende waarde vraagt, is dat je de functie niet opnieuw uitvoert, maar je zegt next van "g".
Dus de volgende is een ingebouwde functie die van invloed is op generatoren,
en het vertelt het om naar de opbrengst te gaan.
Oké, dus als we dit uitvoeren, kun je zien dat we nu nul
krijgen, want dat is het allereerste getal dat wordt opgeleverd.
Nu is onze generator, "g", hier gestopt bij
lijn 4. 5 tussen 4
en 5, dus als we het om een ander nummer vragen, merk dan op dat aan
het einde van een programma de generator wordt
vernietigd, dus als we dit programma opnieuw uitvoeren, zou
dit weer nul zijn en dit zou nu één zijn.
Het onthoudt het niet over programma-uitvoeringen,
dat is gewoon niet hoe Python werkt.
Dus nu kunnen we het voor het eerste nummer vragen, en
dan voor het volgende nummer.
Na het eerste cijfer wordt het tussen
vier en vijf gestopt.
Als we volgende zeggen, gaat het door tot de volgende opbrengst,
wat betekent dat we deze lus één keer herhalen en ons er een geven.
Oke.
Heel belangrijk, de functie onthoudt waar hij is gestopt.
U kunt dus op elk moment de uitvoering van
de functie stoppen en vervolgens de volgende aanroepen om door te gaan.
Het is dus niet alleen handig voor het genereren van nummers of wat dan ook,
het is ook handig als u een functie tijdelijk wilt
stoppen, en dan kunt u deze blijven
uitvoeren wanneer u maar wilt,
door de volgende aan te roepen.
Dus dat is misschien niet
zo logisch op dit moment, maar onthoud dat voor wanneer
we het nodig hebben als we een gesynchroniseerde programmering doen.
Dus hoe zit het met de bereikfunctie?
Ik zei eerder dat dit
in wezen uitlegde hoe de bereikfunctie aan de binnenkant werkt, en dat is
waar, maar de
bereikfunctie geeft je niet direct een generator.
Laten we hier iets doen
als "mijn bereikobject", het wordt
bereik 10.
Dit gedraagt zich heel erg als een generator, maar als
je naast "mijn bereikobject" roept, krijg
je een foutmelding, en kijk daar eens naar.
Dat komt omdat het bereikobject niet echt een generator is,
ook al gedraagt het zich
op deze manier, het genereert geen lijst en
laat je het vervolgens herhalen, het gedraagt zich op deze generatie-achtige manier om
efficiënter te zijn.
"Mijn bereikobject", je kunt
je echter herinneren dat we het
veel eerder in de cursus hebben
uitgeprint en dat we een raar bereik van nul tot tien hebben ontvangen.
Dat is gewoon de "repr"-functie die wordt aangeroepen, en zoals je kunt
zien als we de "repr"-uitkomst afdrukken, zien we ook
een bereik van nul tot tien.
Dus "mijn bereikobject" is iets dat zich ongeveer
zo gedraagt. We gaan in
een paar video's precies leren hoe we een object kunnen herhalen om
het zich als een bereikobject te laten gedragen.
Dus we hebben geleerd over deze generatoren, en nog iets dat
ik eigenlijk wilde noemen, over
de generatoren is dat de lijstfunctie een generator in een lijst kan veranderen.
Dus we kunnen de lijst met "g" afdrukken.
Hier wat we "volgende" hebben genoemd, dan weer
"volgende", en dan "lijst".
Dus nu hebben we nul en één uitgeprint, want dat zijn de twee
dingen in onze "volgende" functies, en
dan hebben we een lijst van de
generator gegenereerd, maar die lijst gaat natuurlijk verder waar we gebleven waren.
De generator onthoudt zelf wat het
was, dus dan begint de lijst bij twee, niet bij nul.
Het is dus heel belangrijk om te onthouden dat
generatoren onthouden waar ze waren.
Dus als je er een maakt, is dat het vanaf het moment dat je het begint te gebruiken,
het moment dat je er "volgende"
op begint te roepen, het onthoudt waar het is,
en je kunt niet teruggaan. Oke.
In de volgende paar video's
gaan we meer leren over generatoren.
We gaan leren over
generatorklassen, hoe je een klasse kunt maken die zich
als een generator gedraagt, en we gaan ook leren over
iterators en iterables in Python, en
de bereikdoelstellingen zijn zo'n voorbeeld.
Dan gaan
we naar enkele functionele programmeervoorbeelden,
zoals filter, kaart, alles en nog wat, en opsommen.
Dus, behoorlijk enthousiast over
deze sectie, ben ik ervan overtuigd dat generatoren iets
zullen zijn dat je nodig zult hebben in
je Python-ontwikkeling, vooral naarmate we verder gaan in de cursus.
Dus dat gezegd hebbende, ik zie je bij de volgende video.