質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

1931閲覧

python 値渡しと参照渡しの違い

nomaluu

総合スコア34

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

3クリップ

投稿2021/07/17 09:23

編集2021/07/17 12:51

質問の経緯

参考書やサイトで値渡しについて、調べても理解できませんでしたので質問しました。

参考書に「参照渡し」について、[関数の呼び出し先で変更を行うと、呼び出し元の変数の値も変更される]という説明がわかりません。
また、pythonには値渡しがないと聞いたのですが、これは参考書が悪いのでしょうか?
サイトのurl:https://www.javadrive.jp/python/userfunc/index3.html
###参考書のコード

値回しのコード
def sell(place):
print(place,'支店の販売が行われました。')

shop= '東京'
sell(shop)

参照渡しのコード
def sell(place):
print(place,'支店の販売が行われました。')

shop=['東京','名古屋','大阪']
sell(shop)

ターミナル

東京 支店の販売が行われました。
['東京', '名古屋', '大阪'] 支店の販売が行われました。

環境

pyhotn3.9.5
エディタ:vscode
os:windows10home

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/07/17 09:30

何がわからなかったのか、もう少し掘り下げていただけないでしょうか?
nomaluu

2021/07/17 09:42

「リテラル」と言うものは、'文字列'や 数値 のことであってますか?
nomaluu

2021/07/17 09:45

回答ありがとうございます。
otn

2021/07/17 09:50

リテラルの意味は概ねあってますが、listリテラルやdictリテラルなどもあります。 メインの質問は、この質問の仕方だと、せっかく説明しても「その説明では分かりません」と言われるのが目に見えているだけに回答しづらいですね。どの辺が理解できないのか書きましょう。
quickquip

2021/07/17 10:22 編集

Pythonに参照渡しは存在せず、値渡ししかないので、Pythonしか知らなければ理解できなくても当たり前です。 参照渡しと値渡しの両方がある言語を持ってこないとそもそも説明は難しいですね。 追加: Pythonの実行モデルにはC言語のような意味での"変数"もないですしね。
nomaluu

2021/07/17 10:24

値渡しは呼び出し後による、影響を元は受けずに、参照渡しは影響を受けるというのはあってますか?
quickquip

2021/07/17 10:32

Pythonに参照渡しは **ない** ですよ。
quickquip

2021/07/17 10:34

BeatStar さんが示したページに合わせて、質問に使う用語を変えることを考えた方がいいですよ という質問への追記・修正の依頼の意図でした。(途中で書き込んでしまいました)
nomaluu

2021/07/17 10:35

不明確な質問ですいません。
BeatStar

2021/07/17 10:56 編集

参考サイトのURLが消えていますよ。 この後から読む人は『ん? なんで参照渡しとかそういう名前が出てきているんだ?』と混乱する可能性があります。(たとえばそのサイトの著者の造語とかだったりするし) 「なぜ疑問に思ったのか」、「なぜそのキーワードが出てきたのか」、「どこがわからないのか」とかをちゃんと書くべきです。 回答者は質問者と同じ環境にある……わけではありません。 他人のことである上、ネットを介しての質問なので顔すら知りません。 面と向かって会話している相手の考えですら完璧にわからないのに、ネットを介していれば なおさらわかるわけないですよね。 なのでちゃんと書いてください。
quickquip

2021/07/17 11:44

自転車のことで質問なのですが、アクセルとクラッチの違いが曖昧です。 みたいな質問になってるのです…… 「まず一体何を読んだら自転車にアクセルとクラッチがあると思ったのか?」というのが率直な反応でしょう。 また「自転車について」質問をしている人が「アクセルとクラッチが分からない」と、そう言っているからといってその人に「四輪自動車では……」とか「バイクでは……」と説明を始めても意味が無いという問題を生んでいます。 四輪自動車でのアクセルとクラッチの説明が、"自転車を運転しようとしている人"の役に立ちますか? という感じです。
nomaluu

2021/07/17 12:38

修正しました。他に編集・修正したほうがいいという意見があったら教えてください。
BeatStar

2021/07/17 12:39

コードは"<code>"または"<コード>"のボタンを押して出てくるヤツの中に書きましょう。
guest

回答3

0

ベストアンサー

また、pythonには値渡しがないと聞いたのですが、これは参考書が悪いのでしょうか?
サイトのurl:https://www.javadrive.jp/python/userfunc/index3.html

参考書では無く、**そのサイトが悪いです。**Pythonには「参照渡し」は存在せず、すべて「値渡し」です。

4. その他の制御フローツール — Python 3.11 ドキュメント#4.7. 関数を定義する

そうすることで、実引数は__値渡し (call by value)__で関数に渡されることになります (ここでの 値 (value) とは常にオブジェクトへの 参照(reference) をいい、オブジェクトの値そのものではありません) [1]。

[1] 実際には、オブジェクトへの参照渡し (call by object reference) と書けばよいのかもしれません。というのは、変更可能なオブジェクトが渡されると、関数の呼び出し側は、呼び出された側の関数がオブジェクトに行ったどんな変更 (例えばリストに挿入された要素) にも出くわすことになるからです。

「オブジェクトへの参照渡し」は「参照渡し(call by reference)」とは異なり物であり、「値渡し」の一種であることに注意してください。「オブジェクトへの参照渡し」は「共有渡し(call by sharing)」や「オブジェクト渡し(call by object)」や「参照の値渡し」(日本のRubyコミュニティでよく使われる表現)と言われるものと同じ評価戦略になります。なお、「参照渡し」と混同しやすいため、「オブジェクトへの参照渡し」を括弧無しで表現することは誤解を生む原因になりますので注意してください。


それを踏まえて、「参照渡し」とは何かです。

[関数の呼び出し先で変更を行うと、呼び出し元の変数の値も変更される]

これをもうちょっと正確に表現すると、このようになります。

[関数の呼び出し先で変数(仮引数)の値に対して変更を行うと、呼び出し元の変数(実引数)の値も変更される]

そう、変更を行うのは変数の値です。実際に「参照渡し」の例をC++で見てみましょう。

C++

1#include <iostream> 2 3void f(int x) { 4 x = 2; 5} 6 7void g(int &x) { 8 x = 3; 9} 10 11int main() { 12 int x = 1; 13 std::cout << x << std::endl; 14 f(x); 15 std::cout << x << std::endl; 16 g(x); 17 std::cout << x << std::endl; 18 return 0; 19}

関数fは値渡し、関数gは参照渡しです。どちらも仮引数に対して代入を行うことで、変数の値そのものを変更しています。fは元の変数に影響はありませんが、gは元の変数に影響がでます。これが、値渡しと参照渡しの違いです。

Pythonの場合、変数の値は「オブジェクトへの参照」です。オブジェクトそのものではありません。そして、Pythonには「値渡し」しか存在しません。同じようなコードをPythonでも書いてみましょう。

def f(x): x = 2 x = 1 print(x) f(x) print(x)

関数gをPythonで表現することは不可能です。なお、次のような例を「参照渡し」と間違った表現をしているサイトがあります。

def h(x): x[0] = 2 x = [1] print(x) h(x) print(x)

それらのサイトが理解していないことは、x[0] = 2は変数xの値を変更しているのでは無いと言うことです。x[0] = 2は変数xの値である「オブジェクトへの参照」が指し示すリストオブジェクトを変更しているということです。変数xの値そのものは何も変更されていません。ですので、この例を持って「参照渡し」と言っているのはプログラミングについてよく知らない素人が何かです。そのような人が書いたサイトを参考にする価値はありません。

投稿2021/07/17 15:09

編集2021/07/17 15:12
raccy

総合スコア21739

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ppaul

2021/07/18 02:29

私の説明よりわかりやすいと思います。 ただし、以下はちょっと違っています。 Pythonの場合、変数の値は「オブジェクトへの参照」です。 C言語の場合には、変数は入れ物で、値は中身なのですが、Pythonの場合は、文字列である名前と値であるオブジェクトの組がどこかにあって、それを束縛と呼び、その名前を変数と呼んでいるだけです。つまりヒモの一方に結ばれているのが名前(変数名)で、もう一方に結ばれているのがオブジェクトです。
raccy

2021/07/18 02:35

「ちょっと違っています」というのはどの部分のことですか?変数の「値」が「オブジェクトへの参照」ではないと言うことですか?
ppaul

2021/07/18 03:46

raccyさんは、説明の中で、「オブジェクトへの参照渡し」を定義していますが、「オブジェクトへの参照」は定義していないですね。定義せずに使うと、それをPythonの文法だと誤解する人が出てくると困ります。 Pythonの文法レベルでは width = 20 は「変数widthに値20を代入する」と表現しています。こういう書き方からすれば変数widthの値は「20への参照」ではなく「20」でしょう。 先ほどのコメントで書いたのは、Pythonの実装レベルでは width = 20 はグローバルなシンボルテーブル(多くの場合、実態は辞書)にwidthをキー、20を値とするエントリーを追加しているだけだということです。 もしもそれを「オブジェクトへの参照」と表現したいなら、先に定義を書いた方が良いのではないですか。
nomaluu

2021/07/18 12:44 編集

文字列ドキュメンテーションとは def my_function(): ... """Do nothing, but document it. ... ... No, really, it doesn't do anything. ... """ ... pass ... の"""~ """ のことでしょうか? また、文字列リテラルは''に囲まれたものをいうのでしょうか? 質問ばかりですいません。
nomaluu

2021/07/18 13:13

これは「質問する」で新たに質問させていただきます。
guest

0

ネットには、信用のできない記事が大量にあふれています。

Pythonの引数における参照渡しと値渡しについての中身はまじめにPythonを使っている人間からすると、トンデモページの典型です。理解する必要はありません。

公式マニュアルを読んでください。

4.6. 関数を定義するには以下のように書かれています。

関数を呼び出す際の実際の引数 (実引数) は、関数が呼び出されるときに関数のローカルなシンボルテーブル内に取り込まれます。そうすることで、実引数は 値渡し (call by value) で関数に渡されることになります (ここでの 値 (value) とは常にオブジェクトへの 参照(reference) をいい、オブジェクトの値そのものではありません) 。

つまり、Pythonでは全ての引数は値渡しであると書いてあります。これは、Pythonの引数の渡し方が「C言語の値渡し」であるという意味ではないので注意してください。

C言語の値渡しとFortranやPL/Iの参照渡しのような概念を無理矢理Pythonに適用しようとすると、Pythonの引数における参照渡しと値渡しについてのような間違った記述をしてしまうのです。

Pythonの場合にもオブエジェクトがイミュータブルであってもハッシュ可能でない場合は、オブジェクトが改変されることがあるのには注意してください。

リテラルについて知りたいということなのですか?

リテラルというのは、Pythonに限らずプログラミング言語で一般に使われる言葉です。

リテラル コンピュータプログラミング
に書いてあることでほぼ合っています。
Pythonのリテラル については、公式マニュアル 2.4. リテラルを読むのが一番確実です。

投稿2021/07/17 09:53

編集2021/07/17 23:23
ppaul

総合スコア24670

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2021/07/17 12:36

C言語の参照渡し?
ppaul

2021/07/17 13:12

ozwkさんの質問の意味が良くわかりません。 私は、「Pythonでは全ての引数は値渡し」という文言を「C言語の値渡し」だと誤解しないでくださいと書いたのですが、これに関する質問ですか?
Zuishin

2021/07/17 13:16

C 言語に参照渡しはないでしょう。
ozwk

2021/07/17 13:20 編集

「C言語の値渡しと参照渡しを無理矢理Pythonに適用しようとすると」というのが 「C言語には値渡しと参照渡しがあって、それらを無理やり...」という意味だとすると C言語に参照渡しはないのでは?ということです (C++なら明確に「参照渡し」という機能がある)
ppaul

2021/07/17 14:14 編集

そういう疑問でしたか。 私のC言語に関する知識は古いので、今の感覚では間違っているかもしれません。 昔のKernighan, Ritchieには、FORTRANは参照渡しだが、Cは値渡しと参照渡しの両方が可能だ、みたいなことが書いてあって、ポインタ変数を渡すことを参照渡しと言っていたのです。これはC++が出るより前の本です。 これがいまだに元C言語利用者がPythonなどの言語の説明で「値渡しと参照渡し」の話が出てくる理由なのだろうと思っています。 おっしゃるとおりC++で&を使った参照渡しが出てきてからはポインタ渡しと書いた方が区別ができて良いのでしょう。 ただ、質問者さんが引用しているサイトで、ああいう誤った解説が出てくるのは、その作者の頭の中にある「値渡しVs参照渡し」の構図のように思えるので、今の回答のままで残しておきます。
Zuishin

2021/07/17 22:16

> 昔のKernighan, Ritchieには、FORTRANは参照渡しだが、Cは値渡しと参照渡しの両方が可能だ、みたいなことが書いてあって、ポインタ変数を渡すことを参照渡しと言っていたのです。 このうろ覚えの情報を正しいものに訂正しないんですか? 手元にあるんでしょう? 参照渡しと書いてありますか?
ppaul

2021/07/17 23:24

確認してみました。私の記憶違いでした。 修正します。
Zuishin

2021/07/17 23:50 編集

C 言語の値渡しとは違うということですが、ただ違うとだけ書かれていて何が違うのかがこの回答では示されていません。 例えば C 言語で構造体を引数に関数を呼び出した場合、その中身をどのように変えても元の構造体には影響を及ぼしません。 しかし、構造体へのポインタを引数にした場合、変更は元の構造体に及びます。 このどちらも値渡しであり、Python のオブジェクトの渡し方は後者に近いものですが、それが理解できていますか? 字面の訂正はされましたが、「古い呼び方では後者は参照渡し」と済ませたところを見ると、根本的に勘違いをしているようにしか思えません。
hentaiman

2021/07/17 23:59

> Python のオブジェクトの渡し方は後者に近いものですが、 質問者視点だとこれだけ教えてもらって、補足でid(とhex)で同じアドレス指してる事を確認できるということを教えてもらえるのが一番嬉しい気がします
ppaul

2021/07/18 02:09

Zuishinさんへ、 例えば C 言語で構造体を引数に関数を呼び出した場合、その中身をどのように変えても元の構造体には影響を及ぼしません。 しかし、構造体へのポインタを引数にした場合、変更は元の構造体に及びます。 実引数に構造体を指定した場合は、構造体全体の中身が仮引数のその構造体のサイズ分コピーされ、多くの実装ではそのコピーはスタックに置かれるというような話なら理解していますよ。 Python のオブジェクトの渡し方については、Python処理系のソースコードを読んでいますので、何をしているかは十分に把握しています。Pythonで書かれた関数とC言語で書かれた関数の実行は、インタプリタが命令を実行する際に切り分けて別の処理を行いますが、そのときの引数を受け渡しするインタフェースは、どちらのばあいもCの引数のインタフェースとは全然違います。 そういう意味で、Pythonの引数の渡し方が「C言語の値渡し」であるという意味ではないのです。
ppaul

2021/07/18 02:11

hentaimanさんへ、 補足でid(とhex)で同じアドレス指してる事を確認できるということを教えてもらえるのが一番嬉しい気がします とのことですが、これはいつも迷うところです。 idが同じか同じでないかという説明は良いのですが、それがアドレスであるのはCpythonの実装にすぎないのですよ。
Zuishin

2021/07/18 02:15

> 実引数に構造体を指定した場合は、構造体全体の中身が仮引数のその構造体のサイズ分コピーされ、多くの実装ではそのコピーはスタックに置かれるというような話なら理解していますよ。 でもポインタを渡した時には参照渡しになると思っていたわけですよね? 言葉だけ覚えなおしたのか、それとも概念自体がわかっていないのかでは、概念自体がわかっていないように読めます。
ppaul

2021/07/18 03:48

いいえ、それのことを「参照渡し」という言葉で表現した本があったと、間違って記憶していただけです。
fana

2021/07/19 03:08

何でしょう,私も,大昔に大学でCを習ったころに「Cで関数引数にポインタを渡すこと」を指して「参照渡し」という語が用いられていたという記憶を持っています…… [Zuishin 2021/07/17 23:16] で示されたリンク先に > 何の注釈もなく「参照渡し」と言う言葉を使っている本が 1冊ありました と書かれていますし,世の中にはそのような本が存在していて,それが不幸にも私が受けた講義で用いられたのかもしれません. (K&Rは買わされただけで講義では全く用いられず,別のでかくて薄っぺらい本が主に使われていたのでそいつのせいかな)
guest

0

Pythonに値渡し・参照渡しがあるかどうかは別として、違いだけを書きます。


違いは『呼び出し側のデータを書き換える(可能性が)あるかどうか』です。

基本的に、(言語によって有無が変わるとか)

値渡し: 値そのものを渡すため、呼び出し側のデータを書き換えない

参照渡し: 参照(C言語でいえばポインタに近い)を渡すため、呼び出し側のデータを書き換えることが出来る

だったはずです。

投稿2021/07/17 10:49

BeatStar

総合スコア4962

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/07/17 12:07

「参照の値渡し」に触れないのは致命的かと思います(Pythonはすべて参照の値渡しで回っています)。
nomaluu

2021/07/17 12:40

「参照の値渡し」というのは「値渡し」と「参照渡し」の合体みたいなものですか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問