Python verim operatörü PHP eşdeğer

6 Cevap php

Python (ve diğerleri), adım adım bir işlevi 'verim' operatörünü kullanarak veri geniş hacimli işleyebilir. Ne PHP bunu benzer şekilde olacaktır?

Örneğin, ben bir potansiyel olarak çok büyük bir dosyayı okumak istedim, ben bu temelde 'file_obj hat için aynı şey olduğu kadar (bu örnekte, yapmacık gibi bir anda her satırda bir işe yarayabilir, Python Diyelim '):

def file_lines(fname):
    f = open(fname)
    for line in f:
        yield line
    f.close()

for line in file_lines('somefile'):
    #process the line

Ne (PHP) şu anda yapıyorum ben devlet izlemek için özel bir örnek değişkeni kullanarak ve buna fonksiyon denir her zaman oyunculuk, ama daha iyi bir yolu olmalı gibi görünüyor olmam.

6 Cevap

PHP generators adında bir doğrudan eşdeğeri vardır.

Old (pre php 5.5 answer):

Ne yazık ki, bir dil eşdeğer değildir. Kolay yolu zaten ne yaptığınızı ya etmektir, ya da durumunu korumak için örnek değişkenleri kullanan bir nesne oluşturmak için.

Orada foreach-deyimi ile birlikte işlevini kullanmak istiyorsanız iyi bir seçenektir ancak şu: SPL Iterators. Bunlar, piton jeneratörleri için oldukça benzer bir şey elde etmek için kullanılabilir.

PHP 5.5 dahil olabilir sadece adresleme https://wiki.php.net/rfc/generators bir rfc vardır.

Arada, bu proof-of-concept kullanıcı adasında uygulanan bir kötü adamın "jeneratör fonksiyonu" check out.

namespace Functional;

error_reporting(E_ALL|E_STRICT);

const BEFORE = 1;
const NEXT = 2;
const AFTER = 3;
const FORWARD = 4;
const YIELD = 5;

class Generator implements \Iterator {
    private $funcs;
    private $args;
    private $key;
    private $result;

    public function __construct(array $funcs, array $args) {
        $this->funcs = $funcs;
        $this->args = $args;
    }

    public function rewind() {
        $this->key = -1;
        $this->result = call_user_func_array($this->funcs[BEFORE], 
                                             $this->args);
        $this->next();
    }

    public function valid() {
        return $this->result[YIELD] !== false;
    }

    public function current() {
        return $this->result[YIELD];
    }

    public function key() {
        return $this->key;
    }

    public function next() {
        $this->result = call_user_func($this->funcs[NEXT], 
                                       $this->result[FORWARD]);
        if ($this->result[YIELD] === false) {
            call_user_func($this->funcs[AFTER], $this->result[FORWARD]);
        }
        ++$this->key;
    }
}

function generator($funcs, $args) {
    return new Generator($funcs, $args);
}

/**
 * A generator function that lazily yields each line in a file.
 */
function get_lines_from_file($file_name) {
    $funcs = array(
        BEFORE => function($file_name) { return array(FORWARD => fopen($file_name, 'r'));   },
        NEXT   => function($fh)        { return array(FORWARD => $fh, YIELD => fgets($fh)); },
        AFTER  => function($fh)        { fclose($fh);                                       },
    );
    return generator($funcs, array($file_name));
}

// Output content of this file with padded linenumbers.
foreach (get_lines_from_file(__FILE__) as $k => $v) {
    echo str_pad($k, 8), $v;
}
echo "\n";

PHP de dahil olmak üzere başka dillerde de uygulamadan önce Python her şeyi prototip. Ben ne yield ile yaptığınız ulaşmak için geri çağrıları kullanarak sona erdi.

function doSomething($callback) 
{
    foreach ($something as $someOtherThing) {
        // do some computations that generates $data

        call_user_func($callback, $data);
    }
}

function myCallback($input)
{
    // save $input to DB 
    // log
    // send through a webservice
    // etc.
    var_dump($input);
}


doSomething('myCallback');

Bu şekilde her $data çağrı işlevine geçirilen ve ne istediğinizi yapabilirsiniz.

Luiz cevap @ genişletme - Başka serin bir şekilde anonim işlevlerini kullanmak için:

function iterator($n, $cb)
{
    for($i=0; $i<$n; $i++) {
        call_user_func($cb, $i);
    }
}

$sum = 0;
iterator(10,
    function($i) use (&$sum)
    {
        $sum += $i;
    }
);

print $sum;

Orada eşdeğer bir operatör olabilir, ama aşağıdaki kod işlevi ve havai eşdeğer olabilir:

function file_lines($file) {
  static $fhandle;

  if ( is_null($fhandle) ) {
    $fhandle = fopen($file, 'r');

    if ( $fhandle === false ) {
      return false;
    }
  }

  if ( ($line = fgets($fhandle))!== false ) {
    return $line;
  }


  fclose($fhandle);
  $fhandle = null;
}

while ( $line = file_lines('some_file') ) {
  // ...
}

Bu konuda doğru görünüyor. Üzgünüm, ben henüz denemedim.

Aynı cümle 'verim' PHP 5.5 şimdi var:

http://php.net/manual/en/language.generators.syntax.php