19

誰かがここで私を助けてくれることを願っています。

私はPythonが初めてで、何が間違っているのかを理解しようとしています。

私はすでに検索して、Python変数をリンクして、一方を変更すると他方が変更されることを発見しましたid()。この概念を理解するために、関数を使用して多数のテストを行いました。しかし、誰かが説明できることを望んでいる例外を見つけたようです...

まず、以下はリストの独立したコピーを作成するために期待どおりに機能します。

>>> a = [0,0]
>>> b = a[:]
>>> print a is b
False
>>> b[0]=1
>>> print a
[0,0]
>>> print b
[1,0]

しかし、これを少し変更するaと、リスト内のリストになり、変更されます...

>>> a = [[0,0],[0,0]]
>>> b = a[:]
>>> print a is b
False
>>> b[0][0]=1
>>> print a
[[1, 0], [0, 0]]
>>> print b
[[1, 0], [0, 0]]

の更新はbにも適用されますがa、 の結果は??をprint a is b返します。Falseこれもチェックしましid()たが、すべてが互いに独立していると言っていますが、一方を更新すると、もう一方にも同じことが当てはまりますか??

誰もこれを説明できますか??

http://labs.codecademy.com/#:workspaceのこれらを実行していることに注意してください。最初に考えたのは、それは彼らのサイトの単なるバグだと思いますが、わかりませんか?

編集:

これまで素晴らしい回答をありがとうございました。それは速かった!これはおそらく以前に質問されたことがあると思いますが、検索するのは困難でした。

すべての答えが正しいので、マークする前に 1 日待ちます。+1が最も多い人がマークを獲得します:)

4

7 に答える 7

18

b = a[:]の浅いコピーを作成するaため、 内の変更可能なリストを変更しても、 内の同じリストb影響します。a

つまり、aandbは同じリストを指しているのではなく (これが理由です)、同じ 2 つのリストa is not bを含む 2 つの異なるリストを指しています。これらのリストの 1 つをで変更すると、その変更が に表示されます。b[0][0] = 1a

で遊んでいたとのことでしid()たので、これを見てください。

>>> a = [[0,0],[0,0]]
>>> b = a[:]
>>> id(a)
2917280                    # <----+
>>> id(b)                  #      |----- different!
2771584                    # <----+
>>> id(a[0]), id(a[1])
(2917320, 2917360)         # <----+
>>> id(b[0]), id(b[1])     #      |----- same!
(2917320, 2917360)         # <----+
于 2013-07-05T21:29:37.077 に答える
13

リストのディープコピーを作成する必要があります。浅いコピーa[:]のみを作成します-ドキュメントを参照してください

関数を使用できcopy.deepcopyます:

>>> import copy
>>> a = [[0,0],[0,0]]
>>> b = copy.deepcopy(a)
>>> b
[[0, 0], [0, 0]]
>>> b[0][0]=1
>>> a
[[0, 0], [0, 0]]
于 2013-07-05T21:29:51.753 に答える
6

何が起こっているかを把握する最も簡単な方法は、視覚的な表現を使用することだと思います (この表現のアイデアは私のものではありませんが、私は気に入っています)。

まず第一に、Python にはオブジェクトへの参照しかないことを理解する必要があります。オブジェクト自体は、互いに別々に存在します。たとえば、 listは、 objectおよびobject への参照[0, 1]を含む list-objectです。参照はある種のリンクです。これは、他の言語の変数とは異なります。変数は一般に、物を置くメモリの場所だからです。Python では、「変数」、つまり識別子は、単にオブジェクトの「名前」(=参照) です。01

これを理解するために、比喩を使って物体間の関係を想像してみましょう。物体は海にある重い岩で、ロープとフック (¿) でつながれているとしましょう。海の表面には、オブジェクトを参照する識別子が住んでいます。識別子は、オブジェクトが深みに沈むのを防ぐブイです(海の怪物(別名ガベージコレクター)がそれらを破壊すると彼らは言います)。

たとえば、この状況を表すことができます。

a = [0, 1]

次の図を使用します。

         ___
        (   )
~~~~~~~~( a )~~~~~~~~
        (___)
 o        ¿      o
          |       O
          |    o
          |
          |
   +------+-------+
   | [  ¿   , ¿ ] |
   +----|-----|---+
        |     |
        |     |
   o    |     |
 O      |     |
        |     |
      +-+-+ +-+-+
      | 0 | | 1 |
      +---+ +---+

 o                 O  o
    )
   (  )             o
  ) )(  )        ( (
 ( (  )( (      ( ) )

ご覧のとおり、識別子a リスト オブジェクトを参照しています。つまり、ロープでリンクされています。list-object には 2 つのスロットがあり、それぞれにオブジェクト0およびに接続されたリンクが含まれています1

さて、もしそうなら:

b = a

識別子はの同じオブジェクトb参照します:a

            ___                 ___
           (   )               (   )
~~~~~~~~~~~( a )~~~~~~~~~~~~~~~( b )~~~~~~~~~~~~~~~~
           (___)               (___)
             ¿                   ¿
              \                 /
    o          \               /             o
  o             \             /            o
                -------+-------
     O         |  [ ¿  ,  ¿ ]  |              O
                ----|-----|----
                    |     |
                  +-+-+ +-+-+
         o        | 0 | | 1 |
                  +---+ +---+              o
    O
       o                              O
                                         o


               )
            ) (                    ) (
         ( (   )(               ( (   )
        ( ) ) (  ) (           ( ) ) (  )

代わりに、次の方法で の浅いコピーを行う場合a:

b = a[:]

新しいリストが作成され、その要素はによって参照されるオブジェクトへの参照のコピーです。つまり、ロープのコピーを作成しましたが、それらは同じ要素を指しています。a

               ___                 ___
               (   )               (   )
    ~~~~~~~~~~~( a )~~~~~~~~~~~~~~~( b )~~~~~~~~~~~~~~~~
               (___)               (___)
    O            ¿                   ¿               o
                 |                   |
       o         |                   |
                 |                   |
          -------+------       ------+-------
         |  [ ¿  , ¿ ]  |     |  [ ¿ ,  ¿  ] |
          ----|----|----       ----|----|----
              |    |               |    |
               \    \             /    /
                \    \           /    /
                 \    \         /    /            o
    o             \    \       /    /           o
                   \    \     /    /               o
       o            \    \   /    /
                     \    \ /    /             o
   O                  \    X    /
                       \  / \  /
                        \/   \/
                        |     |
                        |     |
                        |     |
                      +-+-+ +-+-+
                      | 0 | | 1 |
                      +---+ +---+



                 )
           (    (                  )      (
     )(     )    )  )           ( (   )    )  )
    (  )   (  ) (  (  (       (  ) ) (  ) (  (  (

整数は不変であるため、コピーまたは同じ同一のオブジェクトを使用することに違いはありませんが、整数をmutablelistである s に置き換えると、同じオブジェクトへの参照が変更されるため、表示される動作になります。

視覚的に、コード:

a = [[0, 1], [0, 1]]
b = a[:]

結果:

                ___                 ___
               (   )               (   )
    ~~~~~~~~~~~( a )~~~~~~~~~~~~~~~( b )~~~~~~~~~~~~~~~~
               (___)               (___)
    O            ¿                   ¿               o
                 |                   |
       o         |                   |
                 |                   |
          -------+------       ------+-------
         |  [ ¿  , ¿ ]  |     |  [ ¿ ,  ¿  ] |
          ----|----|----       ----|----|----
              |     \             /     |
              |      \           /      |
              |       \         /       |
              |        \       /        |
              |         \     /         |
              |          \   /          |
              |           \ /           |
              |            X            |
              |           / \           |
              |          /   \          |
              |         /     \         |
              |        /       \        |
              |       /         \       |
              |      /           \      |
              |     |             \     |
              |     |              |    |
         +----+-----+----+   +-----+----+----+
         | [  ¿  ,  ¿  ] |   | [  ¿  ,  ¿  ] |
         +----|-----|----+   +----|-----|----+
               \     \           /     /
                \     \         /     /
                 \     \       /     /
                  \     \     /     /
                   \     \   /     /
                    \     | /     /
                     |    |/     /
                     |    X     /
                     |   / |   /
                     |  /  |  /
                     \ /   \ /
                      Y     Y
                      |     |
                    +-+-+ +-+-+
                    | 0 | | 1 |
                    +---+ +---+


               )
         (    (                  )      (
   )(     )    )  )           ( (   )    )  )
  (  )   (  ) (  (  (       (  ) ) (  ) (  (  (

bリストが の同じサブリストを参照する方法に注意してくださいa。(実装の詳細: CPython のバイトコード コンパイラはリテラル式を最適化し、両方のサブリストで同じオブジェクトが使用されるよう01します。小さな整数にはキャッシュも含まれますが、これは重要ではありません。一般的なケースでは、サブリストにすべての共通の要素)。

ディープ コピーは、この同一オブジェクトの共有を回避するコピーです。

たとえば、実行後:

import copy
a = [[0, 1], [0, 1]]
b = copy.deepcopy(a)

状況は次のとおりです。

                ___                                              ___
               (   )                                            (   )
    ~~~~~~~~~~~( a )~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~( b )~~~~~~~~~~~~~~~~
               (___)                                            (___)
    O            ¿                                                ¿               o
                 |                                                |
       o         |                                                |
                 |                                                |
          -------+------                                   -------+------
         |  [ ¿  , ¿ ]  |                                 |  [ ¿  , ¿ ]  |
          ----|----|----                                   ----|----|----
              |     \                                          |     \
              |      \                                         |      \
              |       \                                        |       \
              |        \                                       |        \
              |         \                                      |         \
              |          \                                     |          \
              |           \                                    |           \
              |            \                                   |            \
              |             \                                  |             \
              |              \                                 |              \
              |               \                                |               \
              |                \                               |                \
         +----+----------+   +--+------------+            +----+----------+   +--+------------+
         | [  ¿  ,  ¿  ] |   | [  ¿  ,  ¿  ] |            | [  ¿  ,  ¿  ] |   | [  ¿  ,  ¿  ] |
         +----|-----|----+   +----|-----|----+            +----|-----|----+   +----|-----|----+
               \     \           /     /                        \     \           /     /
                \     \         /     /                          \     \         /     /
                 \     \       /     /                            \     \       /     /
                  \     \     /     /                              \     \     /     /
                   \     \   /     /                                \     \   /     /
                    \     | /     /                                  \     | /     /
                     |    |/     /                                    |    |/     /
                     |    X     /                                     |    X     /
                     |   / |   /                                      |   / |   /
                     |  /  |  /                                       |  /  |  /
                     \ /   \ /                                        \ /   \ /
                      Y     Y                                          Y     Y
                      |     |                                          |     |
                    +-+-+ +-+-+                                      +-+-+ +-+-+
                    | 0 | | 1 |                                      | 0 | | 1 |
                    +---+ +---+                                      +---+ +---+






               )                                               )
         (    (                  )      (                (    (                  )      (
   )(     )    )  )           ( (   )    )  )      )(     )    )  )           ( (   )    )  )
  (  )   (  ) (  (  (       (  ) ) (  ) (  (  (   (  )   (  ) (  (  (       (  ) ) (  ) (  (  (

(実際には、不変オブジェクトの、、copy.deepcopyなどの不変な組み込みオブジェクトをコピーするのを避けるのに十分賢いようです。そのため、すべてのサブリストは同じオブジェクトとオブジェクトを共有します)intlongtuple01


これらの図は、参照カウントがどのように機能するかを理解するのにも役立つことに注意してください。すべてのロープは参照であり、オブジェクトがブイ (つまり識別子) に到達する参照のチェーンを持つまで、オブジェクトは生き続けます。オブジェクトをサーフェスのブイにリンクするロープがなくなると、オブジェクトは沈み、ガベージ コレクターによって破壊されます。

于 2013-07-05T22:50:40.693 に答える
0

リスト内のリストを扱う場合、計算コストの高いディープコピーに代わる方法があります

origvector=[]
    for ind in range(0, len(testvector)):
        origvector.append(testvector[ind][:])

この例では、"testvector" は n 個のベクトルの行列で、各項目には 3 つの項目のリストが含まれています。このような:

{0,1,2}{10,20,30}
{3,4,5}{40,50,60}
{6,7,8}{70,80,90}
于 2015-12-03T18:11:02.673 に答える