مولدهای پایتون یک ویژگی قدرتمند هستند که امکان تکرار تنبل را از طریق یک سری مقادیر فراهم می‌کنند.

آن‌ها آیتم‌ها را در یک زمان و تنها در صورت نیاز تولید می‌کنند، که آنها را به بهترین انتخاب برای کار با مجموعه‌های داده یا جریان‌های داده بزرگ تبدیل می‌کند که در آن بارگذاری همه چیز به یکباره در حافظه ناکارآمد و غیرعملی است.

روش تعریف و استفاده از ژنراتورها

برای تعریف ژنراتور می توانید از def کلمه کلیدی مانند شما با یک تابع عادی. با این حال، به جای برگرداندن یک مقدار با return، ما استفاده می کنیم yield.

اینجا yield کلمه کلیدی برای تولید یک مقدار و توقف اجرای تابع مولد استفاده می شود. هنگامی که عملکرد از سر گرفته می شود، بلافاصله پس از آن به اجرا ادامه می دهد yield بیانیه.

مثال: ژنراتور ساده

در اینجا یک ژنراتور ساده است که اولین را تولید می کند n شماره:

def simple_generator(n):
    i = 0
    while i < n:
        yield i
        i += 1
        
# Using the generator
gen = simple_generator(5)
for number in gen:
    print(number)

خروجی:

0
1
2
3
4

وقتی که simple_generator() تابع فراخوانی می شود، کد خود را اجرا نمی کند. در عوض، یک شی مولد را برمی گرداند که حاوی یک متد داخلی به نام است __next__()، که با فراخوانی تابع مولد ایجاد می شود.

شی مولد به طور ضمنی از این روش به عنوان یک پروتکل تکرار کننده استفاده می کند وقتی که ما روی مولد تکرار می کنیم.

مزایای استفاده از ژنراتورها

مولدهای پایتون چندین مزیت را ارائه می دهند که کارایی و خوانایی کد را به طور قابل توجهی افزایش می دهد. با تولید کارآمد اقلام روی- the-fly، ژنراتورها استفاده از حافظه را بهینه می کنند و عملکرد را در مقایسه با روش های تکرار شونده سنتی افزایش می دهند.

بیایید برخی از این مزایا را با جزئیات بررسی کنیم و نشان دهیم که چگونه ژنراتورها توسعه پایتون را ساده می کنند و کیفیت کد را بهبود می بخشند.

بهینه سازی حافظه

در مقایسه با لیست هایی که همه عناصر را به یکباره در حافظه بارگذاری می کنند، ژنراتورها بهینه ساز مصرف حافظه هستند. آنها اقلام را یک به یک و فقط در صورت لزوم تولید می کنند.

در اینجا یک مثال است که سناریویی را در نظر می گیرد که در آن باید لیست بزرگی از اعداد تولید کنیم:

# Using a list
numbers = [i for i in range(1000000)]

# Using a generator
def number_generator():
    for i in range(1000000):
        yield i
        
gen_numbers = number_generator()

با لیست، همه 1000000 شماره به طور همزمان در حافظه ذخیره می شوند، اما با مولد، اعداد یک به یک تولید می شوند و مصرف حافظه را کاهش می دهند.

پیشنهاد می‌کنیم بخوانید:  جایگزینی وقوع یک زیر رشته در رشته با جاوا اسکریپت جایگزینی همه یا n مورد از یک زیر رشته در یک رشته معین یک مشکل نسبتاً رایج دستکاری رشته و پردازش متن به طور کلی است. جاوا اسکریپت چند راه برای انجام این کار نسبتاً آسان ارائه می دهد. در این آموزش، چند نمونه از روش جایگزینی وقوع یک ...

عملکرد پیشرفته

از آنجایی که ژنراتورها اقلام تولید می کنند روی- the-fly، آنها عملکرد را به ویژه از نظر سرعت و کارایی افزایش می دهند. آنها می توانند فوراً بدون منتظر ماندن شروع به ارائه نتایج کنند process کل مجموعه داده

در این مثال، بیایید فرض کنیم که نیاز داریم process هر عدد به ترتیب:

# Using a list
numbers = [i for i in range(1000000)]
squared_numbers = [x**2 for x in numbers]

# Using a generator
def number_generator():
    for i in range(1000000):
        yield i
        
def squared_gen(gen):
    for num in gen:
        yield num**2
        
gen_numbers = number_generator()
squared_gen_numbers = squared_gen(gen_numbers)

وقتی از لیست استفاده می کنیم، همه اعداد را تولید می کنیم و سپس process آنها، که زمان بیشتری می برد. با این حال، با مولد، هر عدد به محض تولید پردازش می‌شود و باعث می‌شود process کارآمدتر.

سادگی و خوانایی کد

ژنراتورها در نوشتن کدهای تمیز و خوانا کمک می کنند. آنها به ما اجازه می دهند تا یک الگوریتم تکرار شونده را به روشی ساده، بدون نیاز به کد دیگ بخار برای مدیریت وضعیت تکرار تعریف کنیم. بیایید سناریویی را در نظر بگیریم که در آن باید خطوطی را از یک فایل بزرگ بخوانیم:

# Using a list
def read_large_file(file_name):
    with open(file_name, 'r') as file:
        lines = file.readlines()
    return lines
    
lines = read_large_file('large_file.txt')

# Using a generator
def read_large_file(file_name):
    with open(file_name, 'r') as file:
        for line in file:
            yield line
           
lines_gen = read_large_file('large_file.txt')

با رویکرد لیست، همه خطوط را به یکباره در حافظه می خوانیم. با ژنراتور، ما هر بار یک خط را می‌خوانیم و می‌آوریم، که باعث می‌شود کد ساده‌تر و خواناتر شود و در عین حال به صرفه‌جویی در حافظه کمک می‌کند.

موارد استفاده عملی

این بخش به بررسی موارد استفاده عملی می‌پردازد که در آن ژنراتورهای پایتون برتری می‌یابند، و کشف می‌کند که چگونه ژنراتورها وظایف پیچیده را در عین بهینه‌سازی عملکرد و استفاده از حافظه ساده می‌کنند.

پردازش جریان

ژنراتورها در مدیریت جریان‌های مداوم داده‌ها، مانند داده‌های حسگر بی‌درنگ، جریان‌های گزارش یا فیدهای زنده از APIها عالی هستند. آنها بدون نیاز به ذخیره مقادیر زیادی داده در حافظه، پردازش کارآمد داده را به محض در دسترس بودن فراهم می کنند.

import time

def data_stream():
    """Simulate a data stream."""
    for i in range(10):
        time.sleep(1) # Simulate data arriving every second
        yield 1
        

def stream_processor(data_stream):
    """Process data from the stream."""
    for data in data_stream:
        processed_data = data * 2 # Example processing step
        yield processed_data
        
        
# Usage
stream = data_stream()
processed_stream = stream_processor(stream)
for data in processed_stream:
	print(data)

در این مثال، data_stream() این روش داده ها را در فواصل زمانی تولید می کند و یک جریان داده پیوسته را شبیه سازی می کند. را stream_processor() هر قطعه از داده را هنگام رسیدن پردازش می کند، و نشان می دهد که چگونه مولدها می توانند جریان داده را بدون نیاز به بارگذاری یکباره در حافظه انجام دهند.

پیشنهاد می‌کنیم بخوانید:  جاوا اسکریپت: روش شمارش تعداد رخدادهای زیر رشته ای در یک رشته هنگام کار با رشته ها یا مقادیر زیادی متن، احتمالاً با موقعیت هایی روبرو خواهید شد که باید تعداد دفعات وقوع یک زیررشته خاص در رشته دیگر را بشمارید. در این مقاله، روش استفاده از جاوا اسکریپت برای شمارش تعداد رخدادهای زیر رشته را بررسی خواهیم کرد...

الگوریتم های تکراری

ژنراتورها روشی ساده برای تعریف و اجرای الگوریتم‌های تکراری که شامل محاسبات و شبیه‌سازی‌های تکراری هستند، ارائه می‌کنند. آنها به ما اجازه می دهند تا وضعیت تکرار را بدون مدیریت دستی متغیرهای حلقه حفظ کنیم، که می تواند وضوح کد و قابلیت نگهداری را افزایش دهد.

def fibonacci_generator():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b
        
   
# Usage
fib_gen = fibonacci_generator()
for i in range(10):
	print(next(fib_gen))

در مثال بالا، fibonacci_generator() متد یک مولد را تعریف می کند که اعداد فیبوناچی را به طور نامحدود تولید می کند. هر فیبوناچی شماره یک را در یک زمان برمی گرداند که از 0 و 1 شروع می شود.

اینجا for حلقه 10 بار تکرار می شود تا print 10 عدد اول فیبوناچی، نشان می دهد که چگونه ژنراتورها می توانند به طور موثر توالی ها را بدون بارگذاری اولیه در حافظه تولید و مدیریت کنند.

شبیه ساز بلادرنگ

در این مثال، به‌روزرسانی‌های بی‌درنگ قیمت سهام را شبیه‌سازی می‌کنیم. مولد قیمت سهام جدید را در هر مرحله بر اساس تولید خواهد کرد روی قیمت قبلی و مقداری نوسانات تصادفی

import random
import time

def stock_price_generator(initial_price, volatility, steps):
    """Generates stock prices starting from initial_price with given volatility."""

    price = initial_price
    for _ in range(steps):
        # Simulate price change
        change_percent = random.uniform(-volatility, volatility)
        price += price * change_percent
        yield price
        time.sleep(1) # Simulate real-time delay
        
# Create the stock price generator
initial_price = 100.0 # Starting stock price
volatility = 0.02 # Volatility as a percentage
steps = 10 # Number of steps (updates) to simulate
 
stock_prices = stock_price_generator(initial_price, volatility, steps)
 
# Simulate recieving and processing real-time stock prices
for price in stock_prices:
    print(f"New stock price: {price:.2f}")

این مثال قیمت هر سهام را تولید می کند onبر اساس پرواز روی قیمت قبلی است و تمام قیمت‌های تولید شده را در حافظه ذخیره نمی‌کند و برای شبیه‌سازی‌های طولانی‌مدت کارآمد است.

مولد یک قیمت سهام جدید را در هر مرحله با حداقل محاسبات ارائه می دهد. را time.sleep(1) یک تأخیر بلادرنگ را شبیه سازی می کند و به سیستم اجازه می دهد تا در صورت نیاز سایر وظایف را به طور همزمان انجام دهد.

خلاصه

به طور خلاصه، ژنراتورهای پایتون مدیریت کارآمد حافظه و عملکرد بهبود یافته را ارائه می‌دهند، کد را ساده می‌کنند و در عین حال با وظایف مختلفی مانند پردازش جریان، الگوریتم‌های تکراری و شبیه‌سازی بلادرنگ مقابله می‌کنند.

توانایی آنها در بهینه سازی منابع، آنها را به ابزاری ارزشمند برای توسعه دهندگان پایتون مدرن که به دنبال راه حل های ظریف و مقیاس پذیر هستند تبدیل می کند.

امیدواریم این کاوش در ژنراتورهای پایتون، بینش‌های مورد نیاز برای استفاده از پتانسیل کامل آنها را در اختیار شما قرار دهد. اگر سوالی دارید یا می خواهید بیشتر بحث کنید، با من تماس بگیرید روی لینکدین. علاوه بر این، می توانید در کانال یوتیوب من که در آن ویدیوها را به اشتراک می گذارم مشترک شوید روی تکنیک های کدنویسی و پروژه هایی که دارم کار می کنم روی.