Python

【第3回Python流体の数値計算】「参照渡し」と「値渡し」の違いを理解する。

こんにちは(@t_kun_kamakiri)。

今回は、参照渡し」と「値渡し」というのを理解していきたいと思います。

基本的な内容はこちらのサイトにそってやっていきます。

この記事ではこんな人を対象にしています。

こんな方が対象
  • Pythonを使い始めたけどどう使うかわからない
  • 流体の数値計算をはじめて勉強する人

☟前回の記事がまだの人はこちらから

前回の記事はこちら
本日は、知っておかないと数値計算をしていて「あれ?」って思う場面に遭遇します!!
カマキリ

知っておかないと変なところでドハマりしそうな内容です。

本日の内容はこちら

参照渡し」と「値渡し」について解説をします。

「参照渡し」とか「値渡し」とか名前だけで、うわっめんどくさい内容だなって思うかもしれません。

が、この記事を質問形式にして解説をしたいと思うので、質問に答えることができたらOKです(‘ω’)ノ
では、Google Colaboratoryを使ってコードを書きながら理解を深めていきたいと思います。
スポンサーリンク

質問1:「a = 5」を代入

めちゃくちゃ簡単なところからはじめます。

カマキリ

出力結果はどうなるでしょう?

【結果】

当たり前の結果が返ってきますよね。

 

質問2:「b = a」は?

では、次の場合はどうなるでしょうか?

「a = 5」としておいて、「b」に「a」を代入しています。

カマキリ

出力結果はどうなるでしょう?

【結果】

これも思った通りの結果が返ってきたのではないでしょうか?

質問3:途中で「b = 10」にする

では、これはどうでしょうか?

「a = 5」と始めしておいて、それを「b = a」とします。
そして途中で「b = 10」と値を変更します。

カマキリ

出力結果はどうなるでしょう?

質問の意図は、はじめの「a,bの値」とb変更後の「a,b」の値はどうなっているのか?です。

【結果】

これもあまり難しい内容ではなかったかもしれませんね。

「b」の値だけを変更したから、b変更後のbの値だけが変更されています。
当たり前と言えばそれまでですが、実は配列にしたときにちゃんと理解しておかないと「あれ?」ってなるので解説を加えます。

「変数」というのは値を入れておくための箱のようなもので、そこにはアドレス(番地)が割り振られています。

  • 「a = 5」としたときの変数に対するアドレスは決まっています。
    そこで「b = a」とすると「b」は「a」と同じアドレスを使うことになります。
  • しかし、「b = 10」とすると、変数が再定義されて違うアドレスを用意して値を箱に放り込みます。

こうなっているんですよね。

カマキリ

手っ取り早いのはアドレスを確認してみればいいんです(‘ω’)ノ

というわけでアドレスを確認してみましょう。

idを確認することになるので、以下のように書いて確認をします。

【結果】

変更前は「a,b」ともに同じidだったのに、変更後には「b」のidだけが変わっています。

なるほど「b = 10」と変数を定義しなおすと、違う箱を用意して値を入れるのか・・・・・

というノリで配列にをやると「あれ?」ってなります。

カマキリ

では、次に配列をやります(‘ω’)ノ

 質問3:「参照渡し」について

まずは、☟こちらのコードを書いてみます。

カマキリ

出力結果はどうなるでしょう?

【結果】

そりゃーそうなるよなっていう結果ですね。

では、ここでyの要素の一部を「y[0] = 100」として変更してみます。

カマキリ

出力結果はどうなるでしょう?

【結果】

「あれ?y[0]だけ変えたのに、z[0]も変わってしまった・・・・」ってことになりました。

落ち着いて、アドレス(id)を確認してみましょう。

【結果】

結果を見るとどうやらこういうことみたいです。

  • 「z = y」とすると、変数を再定義しているのではなく「yと同じアドレス内の要素」を受け取りに行っています。
  • 「y[0] = 100」とするとyも変数を再定義しているのではなくて「アドレス内の要素」を変更しているだけです。

ということになります。

これを参照渡しと呼びます。

言葉はわかりにくいのですが、

参照渡し

データを保管しているアドレス自体を変えているのではなくて、アドレス内の要素を変えている

ということです。
これを知っておかないと思いもよらないところで要素が書き換えられる可能性があるので注意です。

質問4:「値渡し」について

では、はじめに定義した変数を変えないようにするにはどうすれば良いのかというと、「z = y.copy()」と書いて別アドレスを用意すれば良いです。
新しく箱を用意するイメージになるでしょう。
☟早速ですが、「質問3」と同じですが、「z = y」ではなく「z = y.copy()」としてみます。

カマキリ

出力結果はどうなるでしょう?

【結果】

「y[0] = 100」となっていますが、z[0]の値は変更を受けていないですよね。

これを理解するためにアドレス(id)を見てみれば理解ができます。

【結果】

これを見ると、「z = y.copy()」としたときに参照渡しと違って、違うアドレスを用意して内容をコピーしていることがわかります。

つまり、絵にしてみると☟こんな感じ。

 

  • 「z = y.copy()」とすると、変数を再定義していて「yとは違うアドレスを用意」して内容をコピーしています。
  • 「y[0] = 100」とするとyも変数を再定義しているのではなくて「アドレス内の要素」を変更しているだけです。
  • 「z[0]」の値はyのアドレスとは関係がないので変更を受けていない。

ということになります。

これを値渡しと呼びます。

言葉はわかりにくいのですが、

値渡し

データを保管しているアドレス自体を変えているので、値を変えても元の変数には影響しない

ということです。

まとめ

本日の内容は、「参照渡し」と「値渡し」という内容でした。

ちょっと理解しにくい部分ではありますが、

  • 参照渡し:要素の変更
  • 値渡し:変数の再定義

とこのように覚えておくと良いでしょう。

では、また(^^)/

前回の記事はこちら

 

Pythonの完全初心者は書籍で学ぶとよい

Python自体が不安だという方は、こちらの書籍から勉強しても良いかも知れません。

☟こちらの本がPython初心者が挫折することなく勉強できる本です。
(本記事のようのPython使用環境と異なりますが、とてもわかりやすいので全く問題ありません)

僕自身もこの書籍ではじめは勉強しました。
小難しい余計なことが書いていないし、年末の一週間くらいで読むことができたので、初心者の方にはとてもお勧めです。
ちょっと応用編として以下の参考書がおすすめです。
Pythonによる数値計算とシミュレーション

Pythonによる数値計算とシミュレーション

小高 知宏
2,750円(03/19 15:11時点)
Amazonの情報を掲載しています
実際に偏微分を離散化して数値計算をするというのを経験することで実力が身につくと思います(^^)/
関連記事もどうぞ

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です