0

次の関数では、L は呼び出しごとに値を格納します。

たとえば、 を呼び出すとf(1)、L は になり[1]ます。もう一度呼び出すと、前の L に新しい値が追加されます。したがって、L は[1,1]です。

def f(a, L=[]):

    L.append(a)
    return L

しかし、この関数では:

i = 5

def f(arg=i):

    print arg
i = 6

この関数を何回呼び出しても、引数はそのまま5です。呼び出し間で更新されたままではありません。

これは更新されないが、リストは更新される理由は何ですか?

4

2 に答える 2

3

これは良い質問です。これが発生する理由は、関数への既定の引数が、関数を呼び出すたびに再作成されるのではなく、単一のオブジェクトとしてメモリに格納されるためです。

したがって[]、デフォルトの引数としてリストがある場合、そのプログラムの期間中、リストは永遠に 1 つだけになります。したがって、リストに追加すると、リストのその 1 つのコピーに追加されます。これは、 のような数値にも当てはまります5。ただし、Python では数値は不変であるため、数値で始まる既定の引数を変更すると、実際には新しい数値を指すようになり、その5オブジェクトを編集するのではなく、リストに対する多くの操作ではリストがその場で変更されます。新しいリストを返すよりも。

http://docs.python.org/3/tutorial/controlflow.html#default-argument-values

重要な警告: デフォルト値は一度だけ評価されます。デフォルトがリスト、辞書、またはほとんどのクラスのインスタンスなどの可変オブジェクトである場合、これは違いを生みます。

関数の呼び出しごとに同じ空のリストのデフォルト引数を持たずに空のリストのデフォルト引数の動作が必要な場合の推奨される解決策は、これを行うことです。

def f(a, L = None):

    if L is None:
        L = []
    L.append(a)
    return L

空のリストの作成は、一度ではなく、関数への個々の呼び出しで評価されるようになりました。

于 2013-05-09T01:26:19.920 に答える
1

a.append()とは異なりi = 6ます。最初のものは配列を変更しますが、配列は同じオブジェクトのままです (同じですが等しくはありません)。一方、後者は変数にまったく新しい値を割り当てます。どのオブジェクトも変更しません (いずれにしても int は可変ではありません)。

于 2013-05-09T01:24:55.990 に答える