3.1 Generatorlarla tanışlıq
Generatorlar — bu, iterator obyektini qaytaran funksiyalardır. Bu iteratorlar dəyərləri tələb olunanda yaradır, bu da potensial olaraq böyük datasetləri tam yaddaşa yükləmədən işləməyə imkan verir.
Generatorlar yaratmağın bir neçə üsulu var, aşağıda onların ən populyar üsulları nəzərdən keçiriləcək.
Funksiyalar əsasında generatorlar
Generatorlar, funksiyanın içərisində olan yield
açar sözü vasitəsilə yaradılır. yield
ilə olan funksiya çağırıldıqda, o bir generator obyekti qaytarır, ancaq dərhal funksiyanın içindəki kodu işə salmır. Bunun əvəzinə, icra yield
ifadəsi üzərində dayandırılır və hər dəfə generator obyektinin __next__()
metodu çağırıldıqda bərpa olunur.
def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1
counter = count_up_to(5)
print(next(counter)) # Çıxış: 1
print(next(counter)) # Çıxış: 2
print(next(counter)) # Çıxış: 3
print(next(counter)) # Çıxış: 4
print(next(counter)) # Çıxış: 5
Əgər funksiyada yield
operatoru varsa, o zaman Python adi funksiya icra etmə üsulundan fərqli olaraq, funksiyanın vəziyyətini idarə edən generator obyekt yaradır.
Generator ifadələri
Generator ifadələri List Comprehension-a bənzəyir, amma kvadrat mötərizələr yerinə dairəvi mötərizələrdən istifadə olunur. Onlar da generator obyekt qaytarır.
squares = (x ** 2 for x in range(10))
print(next(squares)) # Çıxış: 0
print(next(squares)) # Çıxış: 1
print(next(squares)) # Çıxış: 4
Hansı üsul sizə daha çox xoş gəlir?
3.2 Generatorların üstünlükləri
Yaddaşın effektiv istifadəsi
Generatorlar dəyərləri dərhal hesablayır, bu isə böyük məlumatları tamamilə yaddaşa yükləmədən emal etməyə imkan verir. Bu, generatorları böyük məlumat dəstləri və ya məlumat axınları ilə işləmək üçün ideal seçim edir.
def large_range(n):
for i in range(n):
yield i
for value in large_range(1000000):
# Dəyərləri bir-bir emal edirik
print(value)
Tənbəl hesablamalar
Generatorlar tənbəl hesablamalar aparır, yəni, onlar dəyərləri yalnız lazım olduqda hesablayır. Bu, lazımsız hesablamalardan qaçmağa və performansı yaxşılaşdırmağa imkan verir.
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
for _ in range(10):
print(next(fib))
Sintaksis rahatlığı
Generatorlar iteratorlar yaratmaq üçün rahat sintaksis təqdim edir, bu isə kodun yazılmasını və oxunmasını asanlaşdırır.
3.3 Generatorlardan istifadə
Generatorlardan standart kitabxanada istifadə nümunələri
Python-un standart kitabxanasında bir çox funksiya generatorlardan istifadə edir. Məsələn, range()
funksiyası rəqəm ardıcıllığını yaradan generator obyektini qaytarır.
for i in range(10):
print(i)
Bəli, dünya artıq əvvəlki kimi olmayacaq.
Sonsuz ardıcıllıqlar yaratmaq
Generatorlar sonsuz ardıcıllıqlar yaratmağa imkan verir ki, bu da müxtəlif ssenarilərdə, məsələn, sonsuz məlumat axınları yaratmaq üçün faydalı ola bilər.
def natural_numbers():
n = 1
while True:
yield n
n += 1
naturals = natural_numbers()
for _ in range(10):
print(next(naturals))
send()
və close()
istifadəsi
Generator obyektləri send()
və close()
metodlarını dəstəkləyir, bu metodlar generatorun içərisinə dəyər göndərməyə və onun icrasını dayandırmağa imkan verir.
def echo():
while True:
received = yield
print(received)
e = echo()
next(e) # Generatoru işə salırıq
e.send("Salam, dünya!") # Çıxış: Salam, dünya!
e.close()
3.4 Generatorlar praktikada
Generatorlar və istisnalar
Generatorlar istisnaları işləyə bilir, bu da onları daha dayanıqlı kod yazmaq üçün güclü bir alət halına gətirir.
def controlled_execution():
try:
yield "Başla"
yield "İşləyir"
except GeneratorExit:
print("Generator bağlandı")
gen = controlled_execution()
print(next(gen)) # Çıxış: Başla
print(next(gen)) # Çıxış: İşləyir
gen.close() # Çıxış: Generator bağlandı
İstisnalar ilə işi növbəti dərslərdə nəzərdən keçirəcəyik, ancaq düşünürəm ki, sizə generatorların onlarla əla işlədiyini bilməniz faydalı olacaq.
Daxili generatorlar
Generatorlar daxili ola bilər, bu da mürəkkəb iterasiya strukturları yaratmağa imkan verir.
def generator1():
yield from range(3)
yield from "ABC"
for value in generator1():
print(value)
# Çıxış
0
1
2
A
B
C
İzah:
yield from
: Bu konstruksiya əməliyyatların bir hissəsini başqa bir generatora ötürmək üçün istifadə olunur ki, bu da kodu sadələşdirir və oxunaqlılığını yaxşılaşdırır.
Generatorlar və performans
Generatorlardan istifadə yaddaş istifadəsini azaltmaq və iterasiyaların daha səmərəli işlənməsi hesabına proqramların performansını əhəmiyyətli dərəcədə yaxşılaşdıra bilər.
Listlərin və generatorların müqayisəsi nümunəsi
import time
import sys
def memory_usage(obj):
return sys.getsizeof(obj)
n = 10_000_000
# Listdən istifadə
start_time = time.time()
list_comp = [x ** 2 for x in range(n)]
list_time = time.time() - start_time
list_memory = memory_usage(list_comp)
# Generatordan istifadə
start_time = time.time()
gen_comp = (x ** 2 for x in range(n))
gen_result = sum(gen_comp) # Nəticələri müqayisə üçün cəmi hesablayırıq
gen_time = time.time() - start_time
gen_memory = memory_usage(gen_comp)
print(f"List:")
print(f" Zaman: {list_time:.2f} saniyə")
print(f" Yaddaş: {list_memory:,} bayt")
print(f"\nGenerator:")
print(f" Zaman: {gen_time:.2f} saniyə")
print(f" Yaddaş: {gen_memory:,} bayt")
List:
Zaman: 0.62 saniyə
Yaddaş: 89,095,160 bayt
Generator:
Zaman: 1.13 saniyə
Yaddaş: 200 bayt
GO TO FULL VERSION