수색…


왜 발전기를 사용해야합니까?

생성기는 나중에 반복 할 큰 컬렉션을 생성해야 할 때 유용합니다. 그것들은 자주 반복되는 Iterator 를 구현하는 클래스를 만드는 간단한 대안입니다.

예를 들어 아래 함수를 생각해보십시오.

function randomNumbers(int $length)
{
    $array = [];
    
    for ($i = 0; $i < $length; $i++) {
        $array[] = mt_rand(1, 10);
    }
    
    return $array;
}

이 모든 함수는 임의의 숫자로 채워진 배열을 생성합니다. 그것을 사용하기 위해 우리는 randomNumbers(10) 를 할 것입니다. 그러면 10 개의 난수 배열을 얻을 수 있습니다. 100 만 개의 난수를 생성하려면 어떻게해야합니까? randomNumbers(1000000) 는 우리를 대신하여이를 수행하지만 메모리를 소비합니다. 배열에 저장된 백만 개의 정수는 약 33 메가 바이트 의 메모리를 사용합니다.

$startMemory = memory_get_usage();

$randomNumbers = randomNumbers(1000000);

echo memory_get_usage() - $startMemory, ' bytes';

이것은 한 번에 하나씩이 아니라 총 100 만 개의 난수가 생성되어 즉시 반환되기 때문입니다. 발전기는이 문제를 쉽게 해결할 수있는 방법입니다.

생성자를 사용하여 randomNumbers ()를 다시 작성하십시오.

우리의 randomNumbers() 함수는 생성자를 사용하도록 다시 작성할 수 있습니다.

<?php

function randomNumbers(int $length)
{
    for ($i = 0; $i < $length; $i++) {
        // yield tells the PHP interpreter that this value
        // should be the one used in the current iteration.
        yield mt_rand(1, 10);
    }
}

foreach (randomNumbers(10) as $number) {
    echo "$number\n";
}

생성기를 사용하면 함수에서 반환 할 전체 난수 목록을 작성할 필요가 없으므로 사용되는 메모리가 훨씬 적습니다.

생성기로 큰 파일 읽기

생성자의 일반적인 사용 사례 중 하나는 디스크에서 파일을 읽고 내용을 반복하는 것입니다. 아래는 CSV 파일을 반복 할 수있게 해주는 클래스입니다. 이 스크립트의 메모리 사용량은 매우 예측 가능하며 CSV 파일의 크기에 따라 변동하지 않습니다.

<?php

class CsvReader
{
    protected $file;
 
    public function __construct($filePath) {
        $this->file = fopen($filePath, 'r');
    }
 
    public function rows()
    {
        while (!feof($this->file)) {
            $row = fgetcsv($this->file, 4096);
            
            yield $row;
        }
        
        return;
    }
}
 
$csv = new CsvReader('/path/to/huge/csv/file.csv');

foreach ($csv->rows() as $row) {
    // Do something with the CSV row.
}

수율 키워드

yield 문은 return 문과 비슷하지만 함수의 실행을 중지하고 반환하는 대신 yield가 Generator 객체를 반환하고 생성기 함수의 실행을 일시 중지합니다.

다음은 생성자로 작성된 범위 함수의 예입니다.

function gen_one_to_three() {
    for ($i = 1; $i <= 3; $i++) {
        // Note that $i is preserved between yields.
        yield $i;
    }
}

이 함수는 var_dump 의 출력을 검사하여 Generator 객체를 반환 함을 알 수 있습니다.

var_dump(gen_one_to_three())

# Outputs:
class Generator (0) {
}

수익 가치

Generator 객체는 배열처럼 반복 될 수 있습니다.

foreach (gen_one_to_three() as $value) {
    echo "$value\n";
}

위의 예는 다음과 같이 출력됩니다.

1
2
3

키를 사용하여 값 수취하기

값을 산출하는 것 외에도 키 / 값 쌍을 생성 할 수 있습니다.

function gen_one_to_three() {
    $keys = ["first", "second", "third"];

    for ($i = 1; $i <= 3; $i++) {
        // Note that $i is preserved between yields.
        yield $keys[$i - 1] => $i;
    }
}

foreach (gen_one_to_three() as $key => $value) {
    echo "$key: $value\n";
}

위의 예는 다음과 같이 출력됩니다.

first: 1
second: 2
third: 3

send () - 함수를 사용하여 값을 생성기로 전달

생성기는 빠르게 코딩되며 많은 경우 반복기가 많은 구현에 비해 슬림 한 대안입니다. 빠른 구현에서는 발전기가 생성을 멈추거나 다른 것이 생성되어야하는 경우 제어가 약간 부족합니다. 그러나 send() 함수를 사용하여이 작업을 수행 할 수 있습니다. 요청 함수가 매 루프마다 생성기에 매개 변수를 보낼 수 있습니다.

//Imagining accessing a large amount of data from a server, here is the generator for this:
function generateDataFromServerDemo()
{
    $indexCurrentRun = 0; //In this example in place of data from the server, I just send feedback everytime a loop ran through.

    $timeout = false;
    while (!$timeout)
    {
        $timeout = yield $indexCurrentRun; // Values are passed to caller. The next time the generator is called, it will start at this statement. If send() is used, $timeout will take this value.
        $indexCurrentRun++;
    }

    yield 'X of bytes are missing. </br>';
}

// Start using the generator
$generatorDataFromServer = generateDataFromServerDemo ();
foreach($generatorDataFromServer as $numberOfRuns)
{
    if ($numberOfRuns < 10)
    {
        echo $numberOfRuns . "</br>";
    }
    else
    {
        $generatorDataFromServer->send(true); //sending data to the generator
        echo $generatorDataFromServer->current(); //accessing the latest element (hinting how many bytes are still missing.
    }
}

결과물 :

여기에 이미지 설명을 입력하십시오.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow