1. ホーム
  2. python

関数への入力として渡された python 辞書が、その関数ではローカルではなくグローバルのように動作する

2023-08-07 01:30:35

質問

以下の動作に非常に困惑しています。ケース 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.

=============Case 1===============

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

=============Case 2===============

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

=============Case 3===============

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

=============Case 4=============== (この質問で説明しました。 グローバル辞書を変更するためにキーワードglobalを必要としない? )

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

どのように解決するのですか?

Python の "パラメータ評価戦略" は、あなたがおそらく慣れている言語とは少し異なる動作をします。 . 値による呼び出しと参照による呼び出しを明示的に持つ代わりに、Pythonは 共有による呼び出し . 基本的には常にオブジェクト自体を渡すことになり、オブジェクトの変更可能性が変更可能かどうかを決定します。 リストとディクテはミュータブルオブジェクトです。 数値、文字列、タプルはそうではありません。

関数に渡すのは辞書であり、コピーではありません。 したがって、それを変更するときは、元のコピーも変更することになります。

これを避けるには、まず、関数を呼び出す前に辞書をコピーするか、関数内部から(辞書を dict 関数に渡すことで、それを行うことができます。 testfun4(dict(d)) というように関数を定義して def testfun4(d): ).