Добив в Python урок: Generator & Пример за доходност срещу връщане

Какво е Python добив?

Ключовата дума yield в python работи като return с only

разликата е, че вместо да върне стойност, той връща генераторен обект на извикващия.

Когато се извика функция и нишката за изпълнение намери ключова дума yield във функцията, изпълнението на функцията спира на този ред и връща генераторен обект обратно на извикващия.

Синтаксис

yield expression

Descriptйон

Python yield връща генераторен обект. Generators са специални функции, които трябва да бъдат итерирани, за да се получат стойностите.

Ключовата дума yield преобразува дадения израз в генераторна функция, която връща генераторен обект. За да получите стойностите на обекта, той трябва да бъде повторен, за да прочете стойностите, дадени на добива.

Пример: Метод на доходност

Ето един прост пример за добив. Функцията testyield() има ключова дума yield с низа „Добре дошли в Guru99 Python Помагала“. Когато функцията се извика, изходът се отпечатва и дава генераторен обект вместо действителната стойност.

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

Изход:

<generator object testyield at 0x00000028265EB9A8>

Даденият изход е генераторен обект, който има стойността, която сме дали за добив.

Но ние не получаваме съобщението, което трябва да дадем, за да дадем резултат!

За да отпечатате съобщението, дадено на yield, ще трябва да повторите генераторния обект, както е показано в примера по-долу:

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

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

Изход:

Welcome to Guru99 Python Tutorials

Какви са Generatorите в Python?

Generators са функции, които връщат итерируем генераторен обект. Стойностите от генераторния обект се извличат една по една вместо пълния списък заедно и следователно, за да получите действителните стойности, можете да използвате for-цикъл, като използвате метода next() или list().

Използването на Generator функция

Можете да създавате генератори с помощта на функцията на генератора и с помощта на израза на генератора.

Функцията генератор е като нормална функция, вместо да има върната стойност, тя ще има ключова дума yield.

За да създадете генераторна функция, ще трябва да добавите ключова дума yield. Следните примери показват как да създадете генераторна функция.

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

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

Изход:

H
E
L
L
O

Разлика между нормална функция v/s Generator функция.

Нека разберем как функцията на генератора е различна от нормалната функция.

Има 2 функции normal_test() и generator_test().

Предполага се, че и двете функции връщат обратно низа „Hello World“. Normal_test() използва return, а generator_test() използва 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

Изход:

Hello World
<generator object generator_test at 0x00000012F2F5BA20>

Резултатът показва, че когато извикате нормалната функция normal_test(), тя връща низ Hello World. За генераторна функция с ключова дума yield тя връща а не струната.

Това е основната разлика между функцията на генератора и нормалната функция. Сега, за да получим стойността от генераторния обект, трябва или да използваме обекта вътре в цикъла for или да използваме метода next() или да използваме list().

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

Още една разлика, която да добавите към нормалната функция v/s generator функция е, че когато извикате нормална функция, изпълнението ще започне и ще спре, когато стигне до връщане и стойността се връща на повикващия. Така че, когато изпълнението започне, не можете да спрете нормалната функция между тях и тя ще спре само когато попадне на ключова дума return.

Но в случай на генераторна функция, след като изпълнението започне, когато получи първия yield, тя спира изпълнението и връща генераторния обект. Можете да използвате генераторния обект, за да получите стойностите и също така да поставите на пауза и възобновите обратно според вашите изисквания.

Как да прочета стойностите от генератора?

Можете да прочетете стойностите от генераторен обект, като използвате list(), for-loop и използвате next() метод.

Използване на: list()

Списъкът е итерируем обект, чийто елементи са вътре в скоби. Използването на list() върху генераторен обект ще даде всички стойности, които генераторът притежава.

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

Изход:

[0, 2, 4, 6, 8]

Използване на : за в

В примера има дефинирана функция even_numbers(), която ще ви даде всички четни числа за дефинираното n. Извикването на функцията even_numbers() ще върне генераторен обект, който се използва в for-цикъла.

Пример:

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)

Изход:

0
2
4
6
8

Използване на next()

Методът next() ще ви даде следващия елемент в списъка, масива или обекта. След като списъкът е празен и ако се извика next(), той ще върне грешка със сигнал stopIteration. Тази грешка от next() показва, че няма повече елементи в списъка.

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))

Изход:

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

Generatorса за еднократна употреба

В случай на генератори те са достъпни за използване само веднъж. Ако се опитате да ги използвате отново, той ще бъде празен.

Например:

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))

Изход:

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

В случай, че искате изходът да се използва отново, ще трябва да направите повикването да функционира отново.

Пример: Generators и доходност за редицата на Фибоначи

Следващият пример показва как да използвате генератори и yield in Python. Примерът ще генерира редицата на Фибоначи.

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)

Изход:

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

Пример: Извикване на функция с добив

В този пример ще видите как да извикате функция с добив.

Примерът по-долу има функция, наречена test(), която връща квадрата на даденото число. Има друга функция, наречена getSquare(), която използва test() с ключова дума yield. Резултатът дава квадратна стойност за даден диапазон от числа.

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)

Изход:

0
1
4
9
16
25
36
49
64
81

Кога да използвате Yield вместо Return in Python

Python3 Добив ключовата дума връща генератор на извикващия и изпълнението на кода започва само когато генераторът се повтори.

A връщане във функция е краят на изпълнението на функцията и на извикващия се връща една стойност.

Ето ситуацията, когато трябва да използвате Yield вместо Return

  • Използвайте yield вместо return, когато размерът на данните е голям
  • Yield е най-добрият избор, когато имате нужда изпълнението ви да бъде по-бързо при големи набори от данни
  • Използвайте yield, когато искате да върнете голям набор от стойности на извикващата функция
  • Добивът е ефективен начин за генериране на данни, които са големи или безкрайни.

Доходност срещу възвръщаемост

Ето разликите между доходност и възвръщаемост

добив връщане
Yield връща генераторен обект на извикващия и изпълнението на кода започва само когато генераторът се повтори. Връщането във функция е краят на изпълнението на функцията и на извикващия се връща една стойност.
Когато функцията бъде извикана и срещне ключовата дума yield, изпълнението на функцията спира. Той връща генераторния обект обратно на повикващия. Изпълнението на функцията ще започне само когато генераторният обект бъде изпълнен. Когато функцията бъде извикана, изпълнението започва и стойността се връща на извикващия, ако има ключова дума return. Връщането вътре във функцията маркира края на изпълнението на функцията.
израз на добива израз за връщане
Не се използва памет, когато се използва ключовата дума yield. Паметта се разпределя за върнатата стойност.
Много полезно, ако трябва да се справите с огромен обем данни, тъй като паметта не се използва. Удобен за много малък размер на данните.
Производителността е по-добра, ако ключовата дума yield се използва за голям размер на данните. Използва се много памет, ако размерът на данните е огромен, което ще попречи на производителността.
Времето за изпълнение е по-бързо в случай на добив за голям размер на данните. Използваното време за изпълнение е повече, тъй като се извършва допълнителна обработка в случай, че ако размерът на вашите данни е огромен, той ще работи добре за малък размер на данните.

Oбобщение

  • Ключовата дума yield в python работи като връщане с единствената разлика, че вместо да връща стойност, тя връща генераторна функция на извикващия.
  • Генераторът е специален тип итератор, който веднъж използван няма да бъде достъпен отново. Стойностите не се съхраняват в паметта и са достъпни само при извикване.
  • Стойностите от генератора могат да бъдат прочетени с помощта на метода for-in, list() и next().
  • Основната разлика между yield и return е, че yield връща обратно генераторна функция на извикващия, а return дава една стойност на извикващия.
  • Yield не съхранява нито една от стойностите в паметта и предимството е, че е полезно, когато размерът на данните е голям, тъй като нито една от стойностите не се съхранява в паметта.
  • Производителността е по-добра, ако се използва ключовата дума yield в сравнение за връщане за голям размер на данните.