関数の引数で関数の外の値を変えたいんですけどできないんですか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答4件
0
ベストアンサー
追記: 本件からちょっと外れてしまうかもしれませんが、下手に「値渡し」と書いてしまいお馴染みの混乱を招く結果になってしまったようです。
call by value
call by reference
call by sharing
という用語を使うとするとcall by sharingが一番しっくりきそうに思います。(hayataka2049さんありがとうございます)。pythonだけでなくjavaとかC#(の参照型)とか多くの言語でもお馴染みの評価戦略だと思います。call by valueとずっと捉えてたのですがその用語を使うのは控えてcall by sharingといおうと思いました。
以下の元の回答
参照渡しはできません。常に値渡しです。
変更した値を何らかの変更可能なコンポーネントオブジェクト(listとかdictとか)の要素にしておいて、関数の中でコンポーネントオブジェクトの要素を変更するようにすればまぁポインター渡しっぽいことができなくはないです。
ちなみに固定的な変数なのであれば
- グローバル変数ならglobal宣言を用いればできます。
- 外側のローカル変数でもnonlocalを使うとそれができる場面があります。
投稿2018/04/19 04:57
編集2018/04/19 10:15総合スコア18404
0
上から順にお勧めです。
- 戻り値で結果を返すようにする
気軽に複数の要素を返せますし、Cと違ってうっかりフルコピーしてしまうことがないです。
- ミュータブルな要素を引数として渡す
状況によってはこちらが自然です。
- グローバル宣言をして再代入
個人的には禁忌だと思います。『Python global』で調べてください。
なお、
pythonってポインタ渡しみたいなことできないんですか?
もともと全部ポインタ渡しみたいなもんです。
参照値を関数内部で書き換えたときに呼び出し元に影響しないのはCも一緒。
C
1#include <stdio.h> 2 3int the_answer = 42; 4void func(int* arg) { 5 arg = &the_answer; 6 printf("%d\n", *arg); // 42 7} 8 9int main(void) { 10 int var = -1; 11 func(&var); 12 printf("%d\n", var); // -1 13 14 return 0; 15}
Python
1def func(arg): 2 arg = 42 3 print(arg) # 42 4 5var = -1 6func(var) 7print(var) # -1
私が『参照渡し』に期待する動作
C++
1#include<iostream> 2 3void func(int& arg) { 4 arg = 42; 5 std::cout << arg << std::endl; // 42 6} 7 8int main(void) { 9 int val = -1; 10 func(val); 11 std::cout << val << std::endl; // 42 12 13 return 0; 14}
投稿2018/04/19 04:54
編集2018/04/19 10:12総合スコア35676
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
もう質問クローズしてますが、余談として。
Pythonのような言語では、参照渡しの存在を気にする必要がないと感じています。
値渡しだけで事が足りてしまうという意味で。
Python
1def update_a_b_c(a, b, c): 2 a = a * something1 3 b = b + something2 4 c = c / something3 5 return (a, b, c)
something はなんかしらの何かなので気にしないでください。
上記のようにreturnで複数の要素を返却できるので、引数経由で値を返す必要がありません。
Python
1a, b, c = update_a_b_c(a, b, c)
受け取り先で上記のように受け取れば、a, b, cをそれぞれ更新できます。
議論からは逸れていますが、考える必要のないものを考えるのも時間がもったいない、と思いまして一筆取った次第。
投稿2018/04/19 05:52
総合スコア7196
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/04/19 10:53
2018/04/19 11:03
2018/04/19 11:26

0
むしろ逆で、デフォルトでポインタ渡しみたいになっています。それどころか、変数もすべてポインタで実体と結びついていますし。
python
1>>> lst = [] 2>>> def append_lst(lst): 3... lst.append(None) 4... 5>>> lst 6[] 7>>> append_lst(lst) 8>>> lst 9[None]
でもこっちは失敗します。
python
1>>>a = 1 2>>>def add_a(a): 3... a = a + 1 4... 5>>>a 61 7>>>add_a(a) 8>>>a 91
add_aはローカル変数aのポインタが「1」オブジェクトから「2」オブジェクトに張り替えられて終了するだけ。「1」オブジェクトの実体に影響したりはしません。
一応、リストに入れればそれっぽいことはできます。
python
1>>> a = 1 2>>> lst = [a] 3>>> def add_a2(lst): 4... lst[0] = lst[0] + 1 5... 6>>> lst 7[1] 8>>> add_a2(lst) 9>>> lst 10[2]
これは「1」オブジェクトにポインタを張ってるリストを渡して、そのポインタを「2」に張り替える操作をしたんです。
投稿2018/04/19 05:03
総合スコア30939
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/04/19 05:01 編集
退会済みユーザー
2018/04/19 05:04 編集
2018/04/19 05:08 編集
2018/04/19 05:10
2018/04/19 05:15
2018/04/19 05:17 編集
2018/04/19 05:21
2018/04/19 05:28
2018/04/19 08:28
2018/04/19 08:42
2018/04/19 09:37
2018/04/19 10:00
2018/04/19 10:05
2018/04/19 10:09
2018/04/19 10:11 編集
2018/04/19 10:35 編集
2018/04/19 10:13
2018/04/19 10:17
2018/04/19 10:44 編集
2018/04/19 10:31 編集
2018/04/19 10:36
2018/04/19 10:41
2018/04/19 10:44
2018/04/19 12:00 編集
2018/04/19 12:02
2018/04/19 12:33 編集
2018/04/19 12:11
2018/04/19 12:11
2018/04/19 12:20
2018/04/19 12:26
2018/04/19 12:37 編集
2018/04/19 12:41
2018/04/19 12:42 編集
2018/04/19 12:43