وبلاگ سید محمد باقر رکنی

توابع مولد

شنبه, ۱۱ ارديبهشت ۱۳۹۵، ۱۱:۳۸ ب.ظ

تابع مولد چیست؟

توابع مولد خیلی شبیه توابعی  هستند که نتیجه آنها یک آرایه است. با این تفاوت که تابع مولد دنباله ای از مقادیر تولید می کند.

در تابع مولد به جای استفاده از کلمه کلیدی "return" از "yield" جهت  ارسال نتیجه استفاده می شود در تابع مولد  نتیجه  ابجکتیست که از   اینترفیس Iterator استفاده می کند. که بواسطه آن میتوان با دستور foreach مقادیر دنباله را دریافت کرد.


function nums() {
    echo "start"; 
    for ($i = 0; $i < 5; ++$i) {
        yield $i;
        echo "Yielded $i";
    }
    echo "end"; 
}

foreach (nums() as $v);

خروجی

start
Yielded 0
Yielded 1
Yielded 2
Yielded 3
Yielded 4
end

تابع مولد در سایر زبان ها از جمله C sharp,Python,Javascript نیز وجود دارد.

تابع مولد در Python

def file_lines(filename):
    file = open(filename)
    for line in file:
        yield line
    file.close()

for line in file_lines('somefile'):
    #do some work here

خواندن خط به خط فایل با استفاده از تابع مولد

<?php
function file_lines($filename) {
    $file = fopen($filename, 'r'); 
    while (($line = fgets($file)) !== false) {
        yield $line; 
    } 
    fclose($file); 
}

foreach (file_lines('somefile') as $line) {
    // do some work here
}

ارسال کلید

در php شما می توانید علاوه بر ارسال مقدار، کلید مورد نظرتان را نیز ارسال کنید.
<?php
function file_lines($filename) {
    ...
        yield $key => $line; 
    ...
}

foreach (file_lines('somefile') as $key => $line) {
    // do some work here
}

ارسال مقدار به تابع مولد

تابع مولد تنها ارسال کننده نیست بلکه می تواند مقدار نیز دریافت کند. این کار بوسیله متد send انجام می شود.

<?php
function nums() {
    for ($i = 0; $i < 5; ++$i) {
        // get a value from the caller
        $cmd = (yield $i);
        if ($cmd == 'stop') {
            return; // exit the generator
        }
    }
}

$gen = nums();

foreach ($gen as $v) {
    // we are satisfied
    if ($v == 3) {
        $gen->send('stop');
    }
    echo "{$v}n";
}


خروجی کد:

The output will be:

0
1
2
3

صرفه جویی در حافظه بوسیله تابع مولد


چنانچه بخواهید نتیجه حجیم یک تابع را پردازش کنید حافظه زیادی اشغال می شود. توسط تابع مولد می توانید در حافظه صرفه جویی کنید.

مثال:
<?php
// Test 1
$m = memory_get_peak_usage();
foreach (file_lines('lipsum.txt') as $l);
echo memory_get_peak_usage() - $m, "n"; //Outputs 7336

// Test 2
$m = memory_get_peak_usage();
foreach (file('lipsum.txt') as $l);
echo memory_get_peak_usage() - $m, "n"; // Outputs 148112

در نهایت به نظر میرسه مهمترین مزیت توابع مولد صرفه جویی در حافظه باشد.


چنانچه نظر و ایده ای در مورد این موضوع دارید لطفا کامنت بذارید.
  • محمد باقر رکنی

yield

توابع مولد

پایتون

پی اچ پی

نظرات (۱)

سلام و بسیار ممنون از آموزشتون
اگر میشه بیشتر توضیح بدین در دنیای واقعی توابع مولد چه کاربردی دارند
با تشکر.
پاسخ:

با سلام
همانطور که در پایان مطللب ذکر شد هدف اصلی
 توابع مولد صرفه جویی در حافظه است.

به طور مثال تابعی نوشته اید که اطلاعات یک فایل csv  را خوانده و آنها را در یک آرایه ذخیره میکند و باز می گرداند. در صورت استفاده از این تابع حجم بالایی از حافظه توسط آرایه مورد نظر اشغال می شود. چنانچه آن را تبدیل به یک تابع مولد کنید. هر بار فقط به اندازه یک رکورد فایل csv حافظه اشغال می شود.

function readCSV($file) {
    $rows = [];

    $handle = fopen($file, "r");

    while (!feof($handle)) {
        $rows[] = fgetcsv($handle);
    }

    fclose($handle);

    return $rows;
}
function readCSVGenerator($file) {
    $handle = fopen($file, "r");

    while (!feof($handle)) {
        yield fgetcsv($handle);
    }

    fclose($handle);
}
foreach (readCSVGenerator("posts.csv") as $post) {
    // do something with $post
}
ارسال نظر آزاد است، اما اگر قبلا در بیان ثبت نام کرده اید می توانید ابتدا وارد شوید.
شما میتوانید از این تگهای html استفاده کنید:
<b> یا <strong>، <em> یا <i>، <u>، <strike> یا <s>، <sup>، <sub>، <blockquote>، <code>، <pre>، <hr>، <br>، <p>، <a href="" title="">، <span style="">، <div align="">
تجدید کد امنیتی