Prinos u Python tutorial: Generator & Primjer prinosa i povrata

Što je Python prinos?

Ključna riječ yield u pythonu funkcionira kao return s jedinicom

razlika je u tome što umjesto vraćanja vrijednosti vraća objekt generatora pozivatelju.

Kada se funkcija pozove i nit izvršenja pronađe ključnu riječ yield u funkciji, izvršavanje funkcije se zaustavlja na samom retku i vraća objekt generatora natrag pozivatelju.

Sintaksa

yield expression

Description

Python yield vraća objekt generatora. Generators su posebne funkcije koje se moraju ponoviti da bi se dobile vrijednosti.

Ključna riječ yield pretvara dati izraz u funkciju generatora koja vraća objekt generatora. Da bi se dobile vrijednosti objekta, potrebno ga je ponoviti da bi se očitale vrijednosti dane prinosu.

Primjer: Metoda prinosa

Evo jednostavnog primjera prinosa. Funkcija testyield() ima ključnu riječ yield s nizom "Dobrodošli u Guru99 Python Tutoriali“. Kada se funkcija pozove, izlaz se ispisuje i daje objekt generatora umjesto stvarne vrijednosti.

def testyield():
  yield "Welcome to Guru99 Python Tutorials"
output = testyield()
print(output)

Izlaz:

<generator object testyield at 0x00000028265EB9A8>

Dobiveni izlaz je objekt generatora, koji ima vrijednost koju smo dali za prinos.

Ali mi ne dobivamo poruku koju moramo dati da bismo dali rezultat!

Za ispis poruke dane yield-u morat ćete ponoviti objekt generatora kao što je prikazano u primjeru u nastavku:

def testyield():
  yield "Welcome to Guru99 Python Tutorials"

output = testyield()
for i in output:
    print(i)

Izlaz:

Welcome to Guru99 Python Tutorials

Što su Generatorje u Python?

Generators su funkcije koje vraćaju objekt generatora koji se može ponavljati. Vrijednosti iz objekta generatora se dohvaćaju jedna po jedna umjesto cijelog popisa zajedno i stoga da biste dobili stvarne vrijednosti možete koristiti for-petlju, koristeći next() ili list() metodu.

Korištenje Generator funkcija

Možete stvoriti generatore pomoću funkcije generatora i pomoću izraza generatora.

Generatorska funkcija je poput normalne funkcije, umjesto povratne vrijednosti imat će ključnu riječ yield.

Za izradu funkcije generatora morat ćete dodati ključnu riječ yield. Sljedeći primjeri pokazuju kako stvoriti funkciju generatora.

def generator():
    yield "H"
    yield "E"
    yield "L"
    yield "L"
    yield "O"

test = generator()
for i in test:
    print(i)

Izlaz:

H
E
L
L
O

Razlika između normalne funkcije v/s Generator funkcija.

Shvatimo kako se funkcija generatora razlikuje od normalne funkcije.

Postoje 2 funkcije normal_test() i generator_test().

Obje funkcije bi trebale vratiti niz "Hello World". Normal_test() koristi return, a generator_test() koristi yield.

# Normal function
def normal_test():
    return "Hello World"
	
#Generator function
def generator_test():
	yield "Hello World"
print(normal_test()) #call to normal function
print(generator_test()) # call to generator function

Izlaz:

Hello World
<generator object generator_test at 0x00000012F2F5BA20>

Izlaz pokazuje da kada pozovete normalnu funkciju normal_test(), ona vraća niz Hello World. Za funkciju generatora s ključnom riječi yield vraća a ne niz.

Ovo je glavna razlika između funkcije generatora i normalne funkcije. Sada da bismo dobili vrijednost iz objekta generatora, moramo ili upotrijebiti objekt unutar for petlje ili upotrijebiti next() metodu ili upotrijebiti list().

print(next(generator_test()))  # will output Hello World

Još jedna razlika koju treba dodati normalnoj funkciji v/s generatorskoj funkciji je da kada pozovete normalnu funkciju, izvršenje će započeti i zaustaviti se kada dođe do povratak a vrijednost se vraća pozivatelju. Dakle, kada izvođenje započne, ne možete zaustaviti normalnu funkciju između i ona će se zaustaviti samo kada naiđe na ključnu riječ return.

Ali u slučaju funkcije generatora, kada izvođenje započne, kada dobije prvi prinos, zaustavlja izvršenje i vraća objekt generatora. Možete upotrijebiti objekt generatora za dobivanje vrijednosti i također pauzirati i nastaviti prema vašim zahtjevima.

Kako očitati vrijednosti iz generatora?

Vrijednosti iz objekta generatora možete čitati pomoću metode list(), for-loop i next().

Korištenje: list()

Popis je objekt koji se može ponavljati i koji ima svoje elemente unutar zagrada. Korištenje funkcije list() na objektu generatora dat će sve vrijednosti koje generator sadrži.

def even_numbers(n):
    for x in range(n):
       if (x%2==0): 
           yield x       
num = even_numbers(10)
print(list(num))

Izlaz:

[0, 2, 4, 6, 8]

Korištenje: za-u

U primjeru postoji funkcija definirana even_numbers() koja će vam dati sve parne brojeve za definirano n. Poziv funkcije even_numbers() vratit će objekt generatora koji se koristi unutar for-petlje.

Primjer:

def even_numbers(n):
    for x in range(n):
       if (x%2==0): 
           yield x       
num = even_numbers(10)
for i in num:
    print(i)

Izlaz:

0
2
4
6
8

Korištenje next()

Metoda next() dat će vam sljedeću stavku na popisu, nizu ili objektu. Nakon što je popis prazan i ako se pozove next(), vratit će pogrešku sa signalom stopIteration. Ova pogreška iz next() označava da nema više stavki na popisu.

def even_numbers(n):
    for x in range(n):
       if (x%2==0): 
           yield x       
num = even_numbers(10)
print(next(num))
print(next(num))
print(next(num))
print(next(num))
print(next(num))
print(next(num))

Izlaz:

0
2
4
6
8
Traceback (most recent call last):
  File "main.py", line 11, in <module>
    print(next(num))
StopIteration

Generators su jednokratna upotreba

U slučaju generatora dostupni su za korištenje samo jednom. Ako ih ponovno pokušate upotrijebiti, bit će prazna.

Na primjer:

def even_numbers(n):
    for x in range(n):
       if (x%2==0): 
           yield x       
num = even_numbers(10)
for i in num:
    print(i)

print("\n")
print("Calling the generator again: ", list(num))

Izlaz:

0
2
4
6
8
Calling the generator again:  []

U slučaju da želite da se izlaz ponovno koristi, morat ćete ponovno pokrenuti poziv da funkcionira.

Primjer: Generators i prinos za Fibonaccijev niz

Sljedeći primjer pokazuje kako koristiti generatore i prinos Python. Primjer će generirati Fibonaccijev niz.

def getFibonnaciSeries(num):
    c1, c2 = 0, 1
    count = 0
    while count < num:
        yield c1
        c3 = c1 + c2
        c1 = c2
        c2 = c3
        count += 1
fin = getFibonnaciSeries(7)
print(fin)
for i in fin:
    print(i)

Izlaz:

<generator object getFibonnaciSeries at 0x0000007F39C8BA20>
0
1
1
2
3
5
8

Primjer: Pozivanje funkcije s prinosom

U ovom primjeru ćemo vidjeti kako pozvati funkciju s prinosom.

Donji primjer ima funkciju nazvanu test() koja vraća kvadrat zadanog broja. Postoji još jedna funkcija koja se zove getSquare() koja koristi test() s ključnom riječi yield. Izlaz daje kvadratnu vrijednost za zadani raspon brojeva.

def test(n):
    return n*n

def getSquare(n):
    for i in range(n):
        yield test(i)

sq = getSquare(10)
for i in sq:
    print(i)

Izlaz:

0
1
4
9
16
25
36
49
64
81

Kada koristiti Yield umjesto Return in Python

Python3 Prinos ključna riječ vraća generator pozivatelju i izvršavanje koda počinje tek kada se generator ponovi.

A povratak u funkciji je kraj izvršenja funkcije, a pozivatelju se vraća jedna vrijednost.

Ovdje je situacija kada biste trebali koristiti Yield umjesto Return

  • Koristite yield umjesto return kada je veličina podataka velika
  • Yield je najbolji izbor kada vam je potrebno da vaše izvršenje bude brže na velikim skupovima podataka
  • Koristite yield kada želite vratiti veliki skup vrijednosti pozivnoj funkciji
  • Yield je učinkovit način proizvodnje podataka koji su veliki ili beskonačni.

Prinos naspram povrata

Ovdje su razlike između prinosa i povrata

Prinos Povratak
Yield vraća objekt generatora pozivatelju, a izvršavanje koda počinje tek kada se generator ponavlja. Povratak u funkciji je kraj izvršenja funkcije, a pozivatelju se vraća jedna vrijednost.
Kada se funkcija pozove i naiđe na ključnu riječ yield, izvršavanje funkcije se zaustavlja. Vraća objekt generatora natrag pozivatelju. Izvršenje funkcije će započeti tek kada se izvrši objekt generatora. Kada se funkcija pozove, počinje izvršenje i vrijednost se vraća pozivatelju ako postoji ključna riječ return. Povratak unutar funkcije označava kraj izvođenja funkcije.
izraz prinosa povratni izraz
Ne koristi se memorija kada se koristi ključna riječ yield. Memorija se dodjeljuje za vraćenu vrijednost.
Vrlo korisno ako imate posla s velikom količinom podataka jer se memorija ne koristi. Pogodno za vrlo male veličine podataka.
Izvedba je bolja ako se ključna riječ yield koristi za veliku veličinu podataka. Puno se memorije koristi ako je veličina podataka ogromna što će ometati izvedbu.
Vrijeme izvršenja je brže u slučaju prinosa za veliku veličinu podataka. Upotrijebljeno vrijeme izvršenja je više jer se vrši dodatna obrada u slučaju da je veličina vaših podataka ogromna, dobro će funkcionirati za malu veličinu podataka.

Rezime

  • Ključna riječ yield u pythonu funkcionira kao return s jedinom razlikom što umjesto vraćanja vrijednosti vraća funkciju generatora pozivatelju.
  • Generator je posebna vrsta iteratora koji, jednom kada se koristi, više neće biti dostupan. Vrijednosti nisu pohranjene u memoriji i dostupne su samo kada se pozovu.
  • Vrijednosti iz generatora mogu se očitati pomoću metode for-in, list() i next().
  • Glavna razlika između yield i return je u tome što yield vraća funkciju generatora pozivatelju, a return daje jednu vrijednost pozivatelju.
  • Yield ne pohranjuje nijednu vrijednost u memoriju, a prednost je što je od pomoći kada je veličina podataka velika, budući da se niti jedna vrijednost ne pohranjuje u memoriju.
  • Izvedba je bolja ako se koristi ključna riječ yield u usporedbi s povratom za veliku veličinu podataka.