概要
pythonとphpにおける、オブジェクトをループする際の挙動の違いに関する忘備録です。
pythonのforの際に渡される変数は参照渡しで、phpのforeachは値渡しになります。
環境
python anaconda3-5.1.0
php 7.2.10
本文
二次元配列の各配列の末尾に値を追加するという処理を行って確認します。
pythonの挙動
# -*- coding: utf-8 -*-
# 二次元配列
array = [
[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11],
]
# 各配列に要素100を追加する
for row in array:
row += [100]
print(row)
print(array)
出力結果
# for文の中で出力した結果
[0, 1, 2, 3, 100]
[4, 5, 6, 7, 100]
[8, 9, 10, 11, 100]
# for文の外で出力した結果
[[0, 1, 2, 3, 100], [4, 5, 6, 7, 100], [8, 9, 10, 11, 100]]
for文の中と外で出力した結果が同じであることがわかります。
変数rowは、参照渡しで渡されていることが確認できました。
phpの挙動
<?php
// 二次元配列
$array = array(
array(0, 1, 2, 3),
array(4, 5, 6, 7),
array(8, 9, 10, 11),
);
// 各配列に要素100を追加する
foreach ($array as $l) {
$l[] = 100;
print_r($l);
}
print_r($array);
出力結果
// for文の中で出力した結果
Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 100
)
Array
(
[0] => 4
[1] => 5
[2] => 6
[3] => 7
[4] => 100
)
Array
(
[0] => 8
[1] => 9
[2] => 10
[3] => 11
[4] => 100
)
// for文の外で出力した結果
Array
(
[0] => Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
)
[1] => Array
(
[0] => 4
[1] => 5
[2] => 6
[3] => 7
)
[2] => Array
(
[0] => 8
[1] => 9
[2] => 10
[3] => 11
)
)
foreach文の中と外で結果が違うことがわかります。
変数$rowは、値渡しで渡されていることが確認できました。
そのため、配列の中身を変更したつもりなのに反映されてない・・・という事態が起こり得ます。
phpの挙動 補足
しかし、phpで参照渡しにする方法があります。
PHP: foreach - Manual
ループの中で配列の要素を直接変更したい場合は、 $value の前に & をつけます。こうすると、変数には リファレンス が代入されることになります。
知らなかった・・・😱(私だけ?)
というわけで確認します。
foreachの値を渡す際、変数に&をつけて&$rowとして渡します。
<?php
// 二次元配列
$array = array(
array(0, 1, 2, 3),
array(4, 5, 6, 7),
array(8, 9, 10, 11),
);
// 各配列に要素100を追加する
foreach ($array as &$row) {
$row[] = 100;
print_r($row);
}
print_r($array);
出力結果
// for文の中で出力した結果
Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 100
)
Array
(
[0] => 4
[1] => 5
[2] => 6
[3] => 7
[4] => 100
)
Array
(
[0] => 8
[1] => 9
[2] => 10
[3] => 11
[4] => 100
)
// for文の外で出力した結果
Array
(
[0] => Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
[4] => 100
)
[1] => Array
(
[0] => 4
[1] => 5
[2] => 6
[3] => 7
[4] => 100
)
[2] => Array
(
[0] => 8
[1] => 9
[2] => 10
[3] => 11
[4] => 100
)
)
同じ結果になりました。
最後に
久々にphpを触ったので結構戸惑いました。。
各言語によって結構仕様が違ったりするので(特に型周り)気をつけていきたいと思います。
記事に間違いや不明な点があれば遠慮なくご指摘ください。