1. ホーム
  2. パイソン

[解決済み】なぜ関数は、呼び出し元が認識するいくつかの引数を変更でき、他の引数を変更できないのですか?

2022-04-06 01:27:50

質問

Pythonの変数スコープに対する考え方を理解しようとしています。この例では、なぜ f() の値を変更することができます。 x の中で認識される。 main() の値ではありません。 n ?

def f(n, x):
    n = 2
    x.append(4)
    print('In f():', n, x)

def main():
    n = 1
    x = [0,1,2,3]
    print('Before:', n, x)
    f(n, x)
    print('After: ', n, x)

main()

出力します。

Before: 1 [0, 1, 2, 3]
In f(): 2 [0, 1, 2, 3, 4]
After:  1 [0, 1, 2, 3, 4]

解決方法は?

いくつかの回答には、関数呼び出しの文脈で "コピー" という単語が含まれています。紛らわしいと思うのですが。

Pythonはコピーしない オブジェクト 関数呼び出しの際に渡す これまで .

関数のパラメータは 名前 . 関数を呼び出すと、Pythonはこれらのパラメータを(呼び出し元のスコープで名前を使って)渡したオブジェクトに結びつけます。

オブジェクトにはミュータブルなもの(リストのような)とイミュータブルなもの(Pythonの整数や文字列のような)があります。Mutableなオブジェクトは変更することができます。名前を変更することはできませんが、別のオブジェクトにバインドすることはできます。

あなたの例では スコープまたは名前空間 についてです。 ネーミングとバインディング オブジェクトの変更可能性 をPythonで作成しました。

def f(n, x): # these `n`, `x` have nothing to do with `n` and `x` from main()
    n = 2    # put `n` label on `2` balloon
    x.append(4) # call `append` method of whatever object `x` is referring to.
    print('In f():', n, x)
    x = []   # put `x` label on `[]` ballon
    # x = [] has no effect on the original list that is passed into the function

このページには、素敵な写真があります。 他の言語での変数とPythonでの名前の違いについて .