Python Generators

পাইথন জেনারেটর শিখুন

পাইথন - জেনারেটর

ফাংশন যেখানে জেনারেটর তাদের ক্রিয়াকলাপ থামাতে এবং পুনরায় চালু করতে পারে।

জেনারেটর কি?

বিরতি দেওয়ার ক্ষমতা

বৈশিষ্ট্য:বিরতি এবং আন্দোলন পুনরায় শুরু

মূলশব্দ: yield

সুবিধা:স্মৃতিশক্তি

ধীরগতির মূল্যায়ন

বৈশিষ্ট্য:প্রয়োজন অনুযায়ী মান তৈরি করে

পদ্ধতি: Lazy Evaluation

সুবিধা:বড় ডেটার জন্য উপযুক্ত

অসীম সারি

বৈশিষ্ট্য:অন্তহীন অ্যারে তৈরি করে

উদাহরণ: Fibonacci sequence

সুবিধা:মেমরিকে পুরোপুরি কাজে লাগায় না

জেনারেটর ফাংশন

যখন একটি জেনারেটর ফাংশন কল করা হয়, এটি একটি জেনারেটর বস্তু প্রদান করে, যা একটি পুনরাবৃত্তিকারী।

🏁টিপ:

ফাংশনের ভিতরের কোডটি এখনও কার্যকর করা হয়নি, এটি শুধুমাত্র কম্পাইল করা হয়েছে। আপনি যখন জেনারেটর পুনরায় চালু করেন তখনই ফাংশনটি সক্রিয় হয়।

উদাহরণ

একটি সাধারণ জেনারেটর ফাংশন:

def my_generator():
    yield 1
    yield 2
    yield 3

for value in my_generator():
    print(value)

চালানোর জন্য ধাপে ধাপে:

ধাপ 1: my_generator()বলা হয় → একটি জেনারেটর বস্তু প্রদান করে

ধাপ 2:লুপের জন্যnext()কল করে

ধাপ 3:প্রথমyield 1সম্মুখীন হয় → 1 ফেরত দেওয়া হয়

ধাপ 4:পরবর্তীnext()কল করুন →yield 2সঙ্গে দেখা হয়

ধাপ 5:তৃতীয়next()কল করুন →yield 3সঙ্গে দেখা হয়

আউটপুট:1, 2, 3 (প্রতিটি লাইনে)

yieldকীওয়ার্ড

yieldকীওয়ার্ডটি একটি ফাংশন জেনারেটর তৈরি করে।

🔄দ্রষ্টব্য:

yieldদেখা হলে, ফাংশনের অবস্থা সংরক্ষণ করা হয় এবং একটি মান ফেরত দেওয়া হয়। পরের বার জেনারেটরকে কল করা হলে, এটি যেখানে ছেড়েছিল সেখানে চলতে থাকে।

উদাহরণ

নম্বর জেনারেটর:

def count_up_to(n):
    count = 1
    while count <= n:
        yield count
        count += 1

for num in count_up_to(5):
    print(num)

yield vs return

return:অপারেশন সম্পন্ন করে

yield:অপারেশন স্থগিত করে

return:একবারই ডাকা যায়

yield:একাধিকবার ডাকা যায়

অবস্থান সুরক্ষা

স্থানীয় ভেরিয়েবল:সংরক্ষণ করা হয়

প্রোগ্রাম নির্দেশক:সংরক্ষণ করা হয়

ভেরিয়েবল ঢেকে রাখা:সংরক্ষণ করা হয়

পুনরায় আরম্ভ করুন:সঠিক হবে

স্মৃতিশক্তি

জেনারেটরগুলি মেমরি-দক্ষ কারণ তারা মেমরিতে সবকিছু সংরক্ষণ না করেই উড়ে গিয়ে মান তৈরি করে।

উদাহরণ

বড় অ্যারের জন্য জেনারেটর:

def large_sequence(n): আমি পরিসরে (n): ফলন i # এটি মেমরিতে এক মিলিয়ন সংখ্যা তৈরি করে না gen = large_sequence(1000000) প্রিন্ট(পরবর্তী(জেন)) # আউটপুট: 0 প্রিন্ট(পরবর্তী(জেন)) # আউটপুট: 1 প্রিন্ট(পরবর্তী(জেন)) # আউটপুট: 2

তালিকা পদ্ধতি

# মেমরিতে একটি তালিকা তৈরি করে সংখ্যা = [আমি পরিসীমার জন্য i(1000000)] # সমস্ত 1 মিলিয়ন নম্বর মেমরিতে রয়েছে মুদ্রণ(সংখ্যা[0]) # 0 মুদ্রণ(সংখ্যা[1]) # 1 মুদ্রণ(সংখ্যা[2]) # 2

মেমরি ব্যবহার:অনেক

শুরুর গতি:ধীর

আবেদন:ছোট ডেটা

জেনারেটরের পদ্ধতি

# মেমরিতে তালিকা তৈরি করে না def numbers_gen(n): আমি পরিসরে (n): ফলন i gen = numbers_gen(1000000) # একবারে শুধুমাত্র একটি সংখ্যা মেমরিতে থাকে প্রিন্ট(পরবর্তী(জেন)) # 0 প্রিন্ট(পরবর্তী(জেন)) # 1 প্রিন্ট(পরবর্তী(জেন)) # 2

মেমরি ব্যবহার:কম

শুরুর গতি:দ্রুত

আবেদন:বড় তথ্য

next()জেনারেটর ব্যবহার করে

আপনিnext()একটি জেনারেটর ম্যানুয়ালি ফাংশন ব্যবহার করে পুনরায় চালু করা যেতে পারে:

উদাহরণ 1: ম্যানুয়াল রিস্টার্ট

def simple_gen():
    yield "Emil"
    yield "Tobias"
    yield "Linus"

gen = simple_gen()
print(next(gen))  # Output: Emil
print(next(gen))  # Output: Tobias
print(next(gen))  # Output: Linus

উদাহরণ 2: StopIteration

def simple_gen(): ফলন 1 ফলন 2 gen = simple_gen() প্রিন্ট(পরবর্তী(জেন)) # আউটপুট: 1 প্রিন্ট(পরবর্তী(জেন)) # আউটপুট: 2 # মুদ্রণ(পরবর্তী(জেন)) # স্টপআইটারেশন ত্রুটি # ত্রুটি হ্যান্ডলিং gen = simple_gen() চেষ্টা করুন: মুদ্রণ (পরবর্তী (জেনার)) মুদ্রণ (পরবর্তী (জেনার)) প্রিন্ট(পরবর্তী(জেন)) # স্টপআইটারেশন StopIteration ছাড়া: মুদ্রণ ("জেনারেটর ক্লান্ত")

জেনারেটর এক্সপ্রেশন

তালিকা বোঝার মতো, বর্গাকার বন্ধনীর পরিবর্তে বন্ধনী ব্যবহার করে জেনারেটর এক্সপ্রেশন তৈরি করা যেতে পারে:

তালিকা বোঝা

# তালিকা বোঝা - একটি তালিকা তৈরি করে list_comp = [x * x এর জন্য x রেঞ্জে (5)] মুদ্রণ(তালিকা_কম্প) # আউটপুট: [0, 1, 4, 9, 16] মুদ্রণ(টাইপ(লিস্ট_কম্প)) # আউটপুট: <class 'list'>

স্মৃতি:সব আইটেম মেমরি আছে

আবেদন:ছোট ডেটা

জেনারেটর এক্সপ্রেশন

# জেনারেটর এক্সপ্রেশন - জেনারেটর তৈরি করে gen_exp = (x এর জন্য x * x রেঞ্জে (5)) মুদ্রণ(জেন_এক্সপি) # আউটপুট: <জেনারেটর অবজেক্ট <genexpr> 0x...> এ মুদ্রণ(টাইপ(জেন_এক্সপি)) # আউটপুট: <শ্রেণীর 'জেনারেটর'> মুদ্রণ(তালিকা(জেন_এক্সপি)) # আউটপুট: [0, 1, 4, 9, 16]

স্মৃতি:একটি সময়ে শুধুমাত্র একটি আইটেম

আবেদন:বড় তথ্য

একটি বাস্তব উদাহরণ

# তালিকা ছাড়াই বর্গক্ষেত্রের যোগফল গণনা করা হচ্ছে মোট = যোগফল(x * x এর জন্য x রেঞ্জে (10)) মুদ্রণ(মোট) # আউটপুট: 285 # এটি নিম্নলিখিতগুলির চেয়ে ভাল: # মোট = যোগফল([x * x এর জন্য x রেঞ্জে (10)]) # তালিকা তৈরি করে

ফিবোনাচি সিকোয়েন্স জেনারেটর

একটি ফিবোনাচি ক্রম তৈরি করতে জেনারেটর ব্যবহার করা যেতে পারে। এটি মেমরি ফুরিয়ে না গিয়ে অনির্দিষ্টকালের জন্য মান তৈরি করতে থাকবে:

def fibonacci(): a, b = 0, 1 যখন সত্য: ফলন a a, b = b, a + b # প্রথম 10টি ফিবোনাচি নম্বর পান gen = ফিবোনাচি() আমি পরিসীমার জন্য (10): প্রিন্ট(f"Fibonacci({i}): {next(gen)}")

অসীম জেনারেটরের সুবিধা:

স্মৃতি:একবারে মাত্র 2টি সংখ্যা মেমরিতে থাকে

নমনীয়তা:কত নম্বর প্রয়োজন তা নির্ণয় করা যাবে

সমাপ্তি:যে কোন সময় থামতে পারে

পুনরায় আরম্ভ করুন:একটি নতুন জেনারেটর তৈরি করুন

জেনারেটর পদ্ধতি

send()পদ্ধতি

send()পদ্ধতিটি আপনাকে জেনারেটরে একটি মান পাস করতে দেয়:

def echo_generator(): যখন সত্য: প্রাপ্ত = ফলন মুদ্রণ ("প্রাপ্ত:", প্রাপ্ত) gen = echo_generator() next(gen) # জেনারেটর চালু করুন gen.send("হ্যালো") # গৃহীত: হ্যালো gen.send("World") # প্রাপ্ত: বিশ্ব gen.send("Python") # প্রাপ্ত: Python

close()পদ্ধতি

close()পদ্ধতি জেনারেটর বন্ধ করে:

def my_gen():
    try:
        yield 1
        yield 2
        yield 3
    finally:
        print("Generator closed")

gen = my_gen()
print(next(gen))  # Output: 1
gen.close()       # Output: Generator closed
# print(next(gen))  # StopIteration error

throw()পদ্ধতি

throw()পদ্ধতি জেনারেটরের ভিতরে একটি ব্যতিক্রম নিক্ষেপ করা যাক:

def my_gen():
    try:
        yield 1
        yield 2
    except ValueError:
        print("ValueError caught in generator")

gen = my_gen()
print(next(gen))  # Output: 1
gen.throw(ValueError, "Test error")  # Output: ValueError caught in generator

একটি বাস্তব-বিশ্ব অ্যাপ্লিকেশন উদাহরণ

বড় ফাইল প্রক্রিয়াকরণ

def read_large_file(file_path): """জেনারেটর লাইন দ্বারা বড় ফাইল পড়ার জন্য""" ফাইল হিসাবে open(file_path, 'r') সহ: ফাইলের লাইনের জন্য: yield line.strip() # ব্যবহার: # read_large_file ('huge_file.txt') এ লাইনের জন্য: # প্রক্রিয়া_রেখা(লাইন)

ডাটা পাইপ

def number_generator(n): আমি পরিসরে (n): ফলন i def স্কোয়ার_জেনারেটর(সংখ্যা): সংখ্যায় সংখ্যার জন্য: ফলন সংখ্যা * সংখ্যা def filter_even(সংখ্যা): সংখ্যায় সংখ্যার জন্য: যদি সংখ্যা % 2 == 0 হয়: ফলন সংখ্যা # জেনারেটরের পাইপ পাইপলাইন = ফিল্টার_ইভেন(স্কোয়ার_জেনারেটর(সংখ্যা_জেনারেটর(10))) মুদ্রণ(তালিকা(পাইপলাইন)) # [০, ৪, ১৬, ৩৬, ৬৪]

অনুশীলন করুন

নিচের কোডের আউটপুট কি হবে?

def number_generator():
    yield 10
    yield 20
    yield 30

gen = number_generator()
print(next(gen))
print(next(gen))
result = sum(gen)
print(result)

অনুশীলন প্রশ্ন:

10, 20, 60
✗ ভুল! sum(gen) শুধুমাত্র অবশিষ্ট আইটেম যোগ করে (30)। 10 এবং 20 ইতিমধ্যেই ব্যবহৃত হয়েছে।
10, 20, 30
✓ ঠিক আছে! প্রথম পরবর্তী() 10 প্রদান করে এবং দ্বিতীয়টি পরবর্তী() 20 প্রদান করে। sum(gen) অবশিষ্ট আইটেমের যোগফল (30) করবে কারণ জেনারেটর তাদের অবস্থা মনে রাখে।
10, 20, 0
✗ ভুল! sum(gen) খালি নয়। জেনারেটরের আরও একটি আইটেম (30) রয়েছে যা sum() দ্বারা ব্যবহার করা হবে।
একটি ত্রুটি ঘটবে
✗ ভুল! এই কোডে কোন ত্রুটি নেই। সমস্ত ফাংশন বৈধ কারণ sum() একটি জেনারেটর গ্রহণ করে।

সর্বোত্তম অনুশীলন

বড় ডেটার জন্য জেনারেটর ব্যবহার করুন:স্মৃতিশক্তির জন্য
বোঝার জন্য জেনারেটর এক্সপ্রেশন ব্যবহার করুন: (x for x in iterable)
ডেটা পাইপের জন্য জেনারেটর ব্যবহার করুন:একাধিক রূপান্তর একত্রিত করুন
একটি জেনারেটর একাধিকবার পুনরায় চালু করবেন না:যদি তারা রান আউট, পুনর্জন্ম
অসীম ক্রমগুলির জন্য জেনারেটর ব্যবহার করুন:ফিবোনাচি ইত্যাদি
ফাইল প্রক্রিয়াকরণের জন্য জেনারেটর ব্যবহার করুন:এক সময়ে এক লাইন