PHP中for和foreach背后發(fā)生了什么

在循環(huán)結(jié)構(gòu)中,for是很常用的一種表達(dá)式,在學(xué)習(xí)python迭代器的時(shí)候,感覺很有意思,就反過來看看PHP中for和foreach是如何處理的

for和foreach簡(jiǎn)單描述

php中的for處理方式類似于c語言,只要expr2表達(dá)式為真,則循環(huán)會(huì)一直繼續(xù)下去:

for (expr1; expr2; expr3)
    statement

php中的foreach主要是為了遍歷數(shù)組和對(duì)象:
foreach開始執(zhí)行的時(shí)候,數(shù)組內(nèi)部的指針會(huì)自動(dòng)指向第一個(gè)單元,每進(jìn)行一次循環(huán),數(shù)組和對(duì)象的內(nèi)部指針為自動(dòng)移動(dòng)一位,盡量在移動(dòng)的時(shí)候不要修改其值.

foreach (array_expression as $value)
    statement
foreach (array_expression as $key => $value)
    statement

迭代器

上述的forforeach描述很簡(jiǎn)單.

foreach能夠循環(huán)任何迭代器對(duì)象,而這些對(duì)象不僅僅是數(shù)組,可以是任何類型的對(duì)象.
一個(gè)迭代器是一個(gè)對(duì)象,迭代器對(duì)象可能是一個(gè)數(shù)組,也可能是一個(gè)目錄,甚至可以是數(shù)據(jù)庫(kù)查詢結(jié)果集.

SPL(the Standard PHP Library)通過內(nèi)建的類,提供了很大數(shù)量的迭代器,從而讓代碼更有效,更可讀.

The DirectoryIterator class

try {
    $iterator = new \DirectoryIterator($directory);
    foreach ($iterator as $info) {
        if (!$info->isDot() && $info->isFile()) {
            echo $info->__toString() . "\n";
        }
    }
} catch (Exception $e) {
    echo get_class($e) . ": " . $e->getMessage();
}

ArrayIterator

$arr = ["java", "python", "php"];
$iter = new ArrayIterator($arr);
foreach ($iter as $key => $value) {
    echo $key . ":  " . $value . "\n";
}

看一個(gè)另類的用法:

$val = ["shell", "python", "php"];
$arr = new \ArrayIterator($val);
while ($arr->valid()) {
    echo $arr->key() . " : " . $arr->current() . ":" . $arr->offsetGet($arr->key()) . PHP_EOL;
    $arr->offsetSet($arr->key(), "ok");
    $arr->next();
}
print_r($arr->getArrayCopy());

next()方法就是進(jìn)行指針移動(dòng)的關(guān)鍵

為什么使用迭代器

  • 在處理具有大量數(shù)據(jù)的對(duì)象時(shí),使用迭代器比數(shù)組更有效,因?yàn)樵?code>foreach迭代數(shù)組的時(shí)候會(huì)拷貝數(shù)組對(duì)象,而SPL迭代器通過內(nèi)部封裝每一次只會(huì)輸出一個(gè)元素則更有效.
  • 延遲加載,迭代器在使用的時(shí)候能夠加載僅僅需要的數(shù)據(jù)
  • 迭代器真正有用點(diǎn)在于用途比較廣泛,能夠通過實(shí)現(xiàn)迭代器接口創(chuàng)造出更多的數(shù)據(jù)結(jié)構(gòu)

如何創(chuàng)建一個(gè)自定義迭代器

SPL迭代器類已經(jīng)提供了很多功能的迭代器,PHP也提供了接口Iterator,IteratorAggregate讓程序員創(chuàng)建自定義的迭代器類.

只要實(shí)現(xiàn)接口Iterator的五個(gè)方法就可以創(chuàng)建一個(gè)迭代器類,rewind(),current(), key(),next(),valid()

當(dāng)?shù)_始,PHP調(diào)用rewind()方法讓指針回到數(shù)據(jù)集開始處,通過調(diào)用valid()方法檢查數(shù)據(jù)是否可用,假如返回為true,則調(diào)用current()方法獲取當(dāng)前指針對(duì)應(yīng)的值,同時(shí)key()能夠獲取到當(dāng)前指針的key,最后再調(diào)用next()方法重復(fù)上述的流程.

class myIterator implements Iterator {
}

IteratorAggregate
Iterator接口比較適合于創(chuàng)建一個(gè)內(nèi)部的迭代器,理想的情況下,使用IteratorAggregate更加適合創(chuàng)建一個(gè)外部的迭代器,只要實(shí)現(xiàn)getIterator()方法即可.

IteratorAggregateIterator的關(guān)系類似于容器和具體容器的關(guān)系

class myIteratorAggregate implements IteratorAggregate {

    protected $arr = array("php", "python", "shell");
    protected $type;

    function __construct($type = 1) {
        $this->type = $type;
    }

    public function getIterator() {
        if ($this->type == 1)
            return new ArrayIterator($this->arr);
        else
            return new myIterator($this->arr);
    }
}
$obj = new myIteratorAggregate ;
foreach ($obj as $v) {
    echo $v . "\n";
}

總結(jié):

  • 理解迭代器很容易,但是創(chuàng)建一個(gè)有意義的迭代器則不容易,這就類似于學(xué)習(xí)算法可能很容易,但如何實(shí)際運(yùn)用則是另外一回事.
  • 通過SPL迭代器,避免了程序員自造輪子,同時(shí)也提供了更多的數(shù)據(jù)結(jié)構(gòu).
  • 至于使用數(shù)組還是迭代器,則要根據(jù)實(shí)際情況,比如從效率,可讀性等方面衡量.
  • 通過SPL類和接口,PHP提供了更多擴(kuò)展,這也是PHP越來越現(xiàn)代化的證明.
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晓猛,一起剝皮案震驚了整個(gè)濱河市饿幅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌戒职,老刑警劉巖栗恩,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異洪燥,居然都是意外死亡磕秤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門捧韵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來市咆,“玉大人,你說我怎么就攤上這事再来∶衫迹” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵芒篷,是天一觀的道長(zhǎng)搜变。 經(jīng)常有香客問我,道長(zhǎng)针炉,這世上最難降的妖魔是什么挠他? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮篡帕,結(jié)果婚禮上殖侵,老公的妹妹穿的比我還像新娘。我一直安慰自己镰烧,他們只是感情好愉耙,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拌滋,像睡著了一般朴沿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上败砂,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天赌渣,我揣著相機(jī)與錄音,去河邊找鬼昌犹。 笑死坚芜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的斜姥。 我是一名探鬼主播鸿竖,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼沧竟,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了缚忧?” 一聲冷哼從身側(cè)響起悟泵,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎闪水,沒想到半個(gè)月后糕非,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡球榆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年朽肥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片持钉。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡衡招,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出每强,到底是詐尸還是另有隱情始腾,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布舀射,位于F島的核電站窘茁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏脆烟。R本人自食惡果不足惜山林,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望邢羔。 院中可真熱鬧驼抹,春花似錦、人聲如沸拜鹤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽敏簿。三九已至明也,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惯裕,已是汗流浹背温数。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蜻势,地道東北人撑刺。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像握玛,于是被迫代替她去往敵國(guó)和親够傍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子甫菠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • PHP 學(xué)習(xí)目錄 ├─PHP視頻教程 1 LAMP網(wǎng)站構(gòu)建 │ ├─PHP教程 1.1.1 新版視頻形式介紹│ ...
    曹淵說創(chuàng)業(yè)閱讀 16,162評(píng)論 29 417
  • 一 預(yù)定義接口 1.1 遍歷 Traversable(遍歷)接口 檢測(cè)一個(gè)類是否可以被foreach遍歷,該接口不...
    coderhu閱讀 1,208評(píng)論 0 0
  • 聽先生和幾個(gè)堂弟堂妹聊小時(shí)候的事冕屯。幾個(gè)人都說最喜歡也最感謝奶奶寂诱。 堂弟說:“奶奶那么愛干凈,卻總是允許我們把家里弄...
    羽宙兒閱讀 398評(píng)論 0 0
  • 京城秋涼落葉花愕撰,只剩黃綠冷天涯刹衫。 山中還有紅楓美醋寝,曇花一現(xiàn)為晚霞搞挣。
    老槐樹閱讀 142評(píng)論 0 3
  • 當(dāng)代中國(guó)經(jīng)濟(jì)高速發(fā)展嗅绰,生活節(jié)奏不斷加快舍肠,我們?cè)诿τ谧非蟾咂焚|(zhì)生活的同時(shí),卻忽略了自己的健康窘面。調(diào)查發(fā)現(xiàn)翠语,健康人群僅占...
    夕顏李閱讀 478評(píng)論 0 0