78

以下の動作に非常に混乱しています。ケース 1、3、および 4 は期待どおりに動作しますが、ケース 2 はそうではありません。ケース 2 では、辞書が関数によって返されないにもかかわらず、関数が辞書エントリの値をグローバルに変更できるのはなぜですか? 私が関数を使用している主な理由は、関数内のすべてを残りのコードから分離することですが、関数内で同じ変数名を使用することを選択した場合、これは可能ではないようです。関数で明示的に定義されたものはすべてその関数にローカルであると理解していましたが、辞書が定義され、関数への入力として渡された場合、これは当てはまらないようです。

Python 2.7.2+ (default, Oct  4 2011, 20:06:09) 
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.

=============ケース1===============

>>> def testfun1(a):
...     a=2
... 
>>> a=0
>>> testfun1(a)
>>> a
0

=============ケース2===============

>>> def testfun2(b):
...     b['test']=2
... 
>>> b={}
>>> testfun2(b)
>>> b
{'test': 2}

=============ケース3===============

>>> def testfun3():
...     c=2
... 
>>> c=0
>>> testfun3()
>>> c
0

=============ケース 4=============== (この質問で説明:グローバル辞書はそれらを変更するためにグローバルなキーワードを必要としませんか? )

>>> def testfun4():
...     d['test']=10
... 
>>> d={}
>>> testfun4()
>>> d
{'test': 10}
4

5 に答える 5

152

Python の「パラメータ評価戦略」は、おそらく慣れ親しんでいる言語とは少し異なります。明示的な値による呼び出しと参照による呼び出しのセマンティクスを使用する代わりに、Python には共有による呼び出しがあります。基本的に常にオブジェクト自体を渡します。オブジェクトの可変性によって、オブジェクトを変更できるかどうかが決まります。リストと辞書は変更可能なオブジェクトです。数値、文字列、およびタプルはそうではありません。

コピーではなく、辞書を関数に渡しています。したがって、それを変更すると、元のコピーも変更されます。

これを回避するには、まず関数を呼び出す前に、または関数内から辞書をコピーする必要があります (辞書を関数に渡すdict必要があります。つまりtestfun4(dict(d))、関数を として定義しますdef testfun4(d):)。

于 2013-02-25T23:34:47.710 に答える
4

整数や文字列などの基本オブジェクトを関数に渡す場合、関数内でそれを変更しても、関数外の対応するオブジェクトには何も起こりません。これは、基本オブジェクトでリードしている場合、python がそれを値で渡すためです。

ただし、辞書またはリストを関数に渡す場合、それらは参照によって渡されます。つまり、その動作が発生します。関数の外側のオブジェクトが変更されます。

編集: さらに、値渡しと参照渡しには違いがあります。値渡しでは、関数で使用するためにオブジェクトの「コピー」が作成されます。参照により、まったく同じオブジェクトが参照を介して渡され、関数内での変更は外部に表示されます。定義により、python は不変オブジェクトを値で渡し、可変オブジェクトを参照で渡します。

于 2013-02-25T23:38:22.390 に答える
2

グローバル キーワードは、代入にのみ必要です (おそらくdel、試したことはありません)。オブジェクトのミューテーションは完全に有効です。

于 2013-02-25T23:29:37.693 に答える
1

オブジェクトを関数に渡し、dict関数内で変更したため、もちろん関数が戻った後に変更されます。オブジェクトはコピーされないため、渡した同じオブジェクトを変更します。この質問は、オブジェクトを明示的に渡したので、命名、類似の名前、スコープなどとは関係ありません。

于 2013-02-25T23:32:32.400 に答える