一般你在迭代一組數據的時候,需要創建一個數據,假設數組很大,則會消耗很大性能,甚至造成內存不足。
```php
//Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 32 bytes)
range(1, 100000000);
```
PHP5.5實現了生成器,每當產生一個數組元素則用`yield`關鍵詞返回,并且執行函數暫停,當執行函數next方法時,則會從上一次被yield的位置開始繼續執行,如下例子,只會產生中間變量$i,并只在每次循環的賦值;
```php
function xrange($start, $limit, $step = 1) {
for ($i = $start; $i <= $limit; $i += $step) {
//注意變量$i的值在不同的yield之間是保持傳遞的。
yield $i;
}
}
$generator = xrange(1, 100000000, 1);
// 可以通過foreach獲得;
foreach ($generator as $number) {
echo "$number";
echo PHP_EOL;
}
// 由于生成器其實是一個實現了iterator接口的類,所以也可以通過相關的iterator方法來迭代
// var_dump($generator) class Generator#1 (0) {}
// Generator implements Iterator {}
$generator->rewind();
while ($generator->valid()){
echo $generator->current();
echo PHP_EOL;
$generator->next();
}
```
生成器函數的核心是yield關鍵字。它最簡單的調用形式看起來像一個return申明,不同之處在于普通return會返回值并終止函數的執行,而yield會返回一個值給循環調用此生成器的代碼并且只是暫停執行生成器函數。
## 通過生成器來生成關聯數組
```php
/*
* 下面每一行是用分號分割的字段組合,第一個字段將被用作鍵名。
*/
$input = <<<'EOF'
1;PHP;Likes dollar signs
2;Python;Likes whitespace
3;Ruby;Likes blocks
EOF;
function input_parser($input) {
foreach (explode("\n", $input) as $line) {
$fields = explode(';', $line);
$id = array_shift($fields);
yield $id => $fields;
}
}
foreach (input_parser($input) as $id => $fields) {
echo "$id:\n";
echo " $fields[0]\n";
echo " $fields[1]\n";
}
/*
1:
PHP
Likes dollar signs
2:
Python
Likes whitespace
3:
Ruby
Likes blocks
*/
```
## 生成NULL值
略;
## 使用引用來生成值
先了解一下從函數返回一個引用的概念
手冊解釋: 引用返回用在當想用函數找到引用應該被綁定在哪一個變量上面時。不要用返回引用來增加性能,引擎足夠聰明來自己進行優化。僅在有合理的技術原因時才返回引用!要返回引用,使用此語法:
**Example: 使用返回引用**
```php
class foo{
public $value = 42;
public function &getValue()
{
return $this->value;
}
}
$obj = new foo;
// $myValue is a reference to $obj->value, which is 42.
// $myValue 是 $obj->value 的引用,它們的值都是 42
$myValue = &$obj->getValue();
// 對 $obj->value 重新賦值,會影響到 $myValue 的值
$obj->value = 2;
// prints the new value of $obj->value, i.e. 2.
echo $myValue; // 程序輸出 2
```
**Example: 沒有使用返回引用**
```php
class foo {
public $value = 42;
public function getValue() {
return $this->value;
}
}
$obj = new foo;
$myValue = $obj->getValue();
$obj->value = 2;
echo $obj->value; // 輸出 2
echo $myValue; // 輸出42, 因為返回的是當時值的一個副本;
```
函數 &getValue() 把引用綁定在成員變量 $value 上了。正常來說,$obj = new foo; 產生的 $obj 是一個copy,它的成員變量 $value 與函數 getValue() 不存在“別名”(引用)關系。
**Example: 通過引用來生成值**
```php
function &gen_reference() {
$value = 3;
while ($value > 0) {
yield $value;
}
}
/*
* 我們可以在循環中修改$number的值,而生成器是使用的引用值來生成,所以gen_reference()內部的$value值也會跟著變化。
*/
foreach (gen_reference() as &$number) {
echo (--$number).'...';//改變的是gen_reference()里面的$value值;這樣里面的循環就不是死循環了。
}
```
## yield from關鍵字
在PHP7的版本,生成器允許從其他生成器,可迭代對象或數組通過`yield from`關鍵字來生成對應的值;
```php
function count_to_ten() {
yield 1;
yield 2;
yield from [3, 4];
yield from new ArrayIterator([5, 6]);
yield from seven_eight();
yield 9;
yield 10;
}
function seven_eight() {
yield 7;
yield from eight();
}
function eight() {
yield 8;
}
foreach (count_to_ten() as $num) {
echo "$num ";
}
// 輸出1 2 3 4 5 6 7 8 9 10
```
- 現代化PHP特性
- php7常用特性整理
- 反射機制Reflection
- 依賴注入與服務容器
- 抽象類與接口
- 類多繼承的替代方案Traits
- 類的延遲綁定(后期綁定)
- 生成器語法
- 匿名函數和閉包
- 匿名類
- 理解php的output buffer
- 斷言ASSERT
- 魔術方法小結
- Zend Opcache字節碼緩存
- 內置的http服務器
- SPL標準庫
- 【SPL標準庫專題(1)】SPL簡介
- 【SPL標準庫專題(2)】Iterator
- 【SPL標準庫專題(3)】Classes
- 【SPL標準庫專題(4)】Exceptions
- 【SPL標準庫專題(5)】Datastructures:SplDoublyLinkedList
- 【SPL標準庫專題(6)】Datastructures:SplStack & SplQueue
- 【SPL標準庫專題(7)】Datastructures:SplPriorityQueue
- 【SPL標準庫專題(8)】Datastructures:SplHeap & SplMaxHeap & SplMinHeap
- 【SPL標準庫專題(9)】Datastructures:SplFixedArray
- 【SPL標準庫專題(10)】Datastructures:SplObjectStorage
- PHPcomposer使用手札[ing]
- PHP中的多態
- 通過命名空間實現自動加載的框架雛形
- 日期與金額
- PHPstorm使用攻略
- 筆記本