0

重複の可能性:
引数としてリストを渡す Python

それについて多くのトピックを探しましたが、実際に何が起こっているのか理解できません。

私はこのコードを持っています:

def altera(L1, L2):
    for elemento in L2:
        L1.append(elemento)
    L2 = L2 + [4]
    L1[-1] = 10
    del L2[0]
    return L2[:]

Lista1 = [1,2,3]
Lista2 = [1,2,3]

Lista3 = altera(Lista1, Lista2)

print Lista1
print Lista2
print Lista3

結果は次のとおりです。

[1, 2, 3, 1, 2, 10]
[1, 2, 3]
[2, 3, 4]

Lista1がどのように変更され、変更されなかったのか理解できませLista2ん。ただし、コードをテストする前に、それらはグローバル変数であるため、変更されないままになるLista1と思いました。Lista2

4

4 に答える 4

3

Python では、リストは参照によって渡されます。Lista1を直接呼び出すため、 が変更されます.append:

for elemento in L2:
    L1.append(elemento)

Lista2リストを変更していないため、 は変更されません。を変更しない加算演算子 を使用しましL2 = L2 + [4]た。代わりに、新しいリストを作成して結果を返します。 L2

「参照渡し」という用語を Google で検索すると、Python で適切な説明の例を見つけることができるはずです。

于 2013-01-22T19:18:54.200 に答える
0

これを行うL1.append(elemento)ときは、変数によって指定されたリストを実際に変更するメソッドを呼び出していますL1L1との値を設定する他のすべてのコマンドは、L2実際には新しい変数の新しい名前を作成しているだけです。

このバージョンは何も変更しません:

def altera(L1, L2):
    for elemento in L2:
        # create a new list and assign name L1
        L1 = L1 + [elemento]
    # create a new list and assign name L2
    L2 = L2 + [4]
    return L2

Lista1 = [1,2,3]
Lista2 = [1,2,3]

Lista3 = altera(Lista1, Lista2)

print Lista1
print Lista2
print Lista3

これはしますが:

def altera(L1, L2):
    for elemento in L2:
        # Call method on L1 that changes it
        L1.append(elemento)
    # Call method on L2 that changes it
    L2.append(4)
    # Change object pointed to by name L1 -- Lista1
    L1[-1] = 10
    # Change object pointed to by name L2 -- Lista2
    del L2[0]
    return L2[:]

Lista1 = [1,2,3]
Lista2 = [1,2,3]

Lista3 = altera(Lista1, Lista2)

print Lista1
print Lista2
print Lista3

L += [2]ただし、とまったく同じではないトリッキーな問題がありL = L + 2ます。拡張代入ステートメントのPython言語リファレンスの セクションでは、違いについて説明しています。

x + = 1のような拡張代入式は、x = x + 1として書き直すことができます。これにより、同様の効果が得られますが、まったく同じ効果は得られません。拡張バージョンでは、xは1回だけ評価されます。また、可能な場合は、実際の操作がインプレースで実行されます。つまり、新しいオブジェクトを作成してそれをターゲットに割り当てるのではなく、古いオブジェクトが変更されます。」</ p>

于 2013-01-22T19:14:41.997 に答える
0

L2ステートメントを使用して名前に新しい値を割り当てるとL2 = L2 + [4]、それはもはや参照しませんLista2。他のステートメントのほとんどは、それらがすでに参照しているオブジェクトの値を変更します。

于 2013-01-22T19:16:25.727 に答える
0

関数では、次の 2 つの異なる処理が行われます。

def altera(L1, L2):
    for elemento in L2:
        L1.append(elemento)
        # [1] this ^ alters L1 in place
    L2 = L2 + [4]
    # [2] this ^ creates a new list
    L1[-1] = 10
    del L2[0]
    return L2[:]

インラインで追加したコメントを拡張するには:

  1. 内部alteraでは、変数L1 あなたが渡したものです(つまりです Lista1)。これはコピーではなく、同じ内容の新しいリストです - 同じ実際のオブジェクトを参照しています
  2. 割り当てるときは、L2 = L2 + [4]次の 2 つのことを行います。

    1. 値を持つ新しいリストを作成しますL2 + [4]
    2. L2渡したものの代わりに、この新しいリストを指すように設定します

    変数の名前を変更すると、明示的になり、まったく同じように機能します。

    L3 = L2 + [4]
    del L3[0]
    return L3[:]
    

    あるいは、オリジナルL2をその場で変更したい (つまり、実際に変更しLista2たい) 場合は、次のようにします。

    L2.append(4)
    del L2[0]
    return L2[:]
    

    最後の行はLista3、 とは異なるリスト オブジェクトになることを意味Lista2しますが、同じ値を持つことに注意してください。だけの場合return L2、は と同じLista3なるため、同じリスト オブジェクトの 2 つの名前になります。L2

この動作を防ぎたい場合は、次alteraのように呼び出すことができます。

Lista3 = altera(Lista1[:], Lista2[:])

現在、内部alteraでは、引数の独自のコピーで動作し、元のLista1andに影響を与えることはできませんLista2

于 2013-01-22T19:23:22.617 に答える