5

代入の (一見) 奇妙な動作に気付きました。これにより、何度かプログラミングの間違いを犯してきました。

最初に次の例を参照してください。

>>> i = 0
>>> t = (i,)
>>> t
(0,)
>>> i += 1
>>> t
(0,)

予想どおり、 の値がインクリメントされた後でも、 の一意の要素の値はt変わりません。i

次を参照してください。

>>> l = [0]
>>> t = (l,)
>>> t
([0],)
>>> l[0] += 1
>>> t
([1],)  # <- ?

t最初の zero inが oneになった理由がわかりません。t...への参照でそれをインクリメントした場合

>>> t[0][0] += 1

... 値が変更されたことは理解できますが、前の例では だけlが増加するときに明示的に参照されているため、これは当てはまりません。

2 つの質問があります。

  1. なぜそうなのですか?
  2. これに関して知っておくべき特別なルールはありますか?
4

2 に答える 2

8

これは、整数が不変であり、リストが可変であるためです。

>>> i = 0
>>> t = (i,)
>>> t[0] is i  # both of them point to the same immutable object
True
>>> i += 1  # We can't modify an immutable object, changing `i` simply 
            # makes it point to a new object 2.
            # All other references to the original object(0) are still intact.
>>> i
1
>>> t       # t still points to the same 0
(0,)
>>> x = y = 1
>>> id(x),id(y)
(137793280, 137793280)
>>> x += 1
>>> id(x),id(y)       #y still points to the same object
(137793296, 137793280)

リストの場合:

>>> l = [0]
>>> t = (l,)       
>>> t[0] is l #both t[0] and l point to the same object [0]
True
>>> l[0] += 1 # modify [0] in-place
>>> t
([1],)
>>> l
[1]
#another exmple
>>> x = y =[]    # x, y point to the same object
>>> x.append(1)  # list.append modifies the list in-place
>>> x, y          
([1], [1]) 
>>> x = x + [2]  # only changes x, x now points to a new object
>>> x, y
([1, 2], [1])
于 2013-06-10T12:31:02.290 に答える
2

2 番目の例では、t(タプル) はl(リスト) への参照を保持します。するとl[0] += 1、リストが変更されますが、タプルはまだリストへの参照を保持しています。最初の例では、 を実行するとi += 1、実際には、タプルが参照を保持しない新しい整数を作成しています。オペレーターとそれが実際にどのように実装されているかについてのより詳細な説明については、私がしばらく前に書いたこの回答を参照してください。+=

于 2013-06-10T12:35:17.420 に答える