2

重複の可能性:
オブジェクトと基本型の割り当て

a = [1,2,3]
b = a
print b is a

このコードは True を出力します。なんで?「is」は、2 つの変数が同じオブジェクトを指している場合にのみ True を返します。この場合、それらは同じ値を持つ異なるオブジェクトです。"==" は True を返しますが、"is" は返すべきではありません。

ただし、

b.reverse()
print a,b

[3, 2, 1] [3, 2, 1] を出力すると、インタプリタに関する限り、それらは同じオブジェクトであり、b に対する操作は自動的に a に対して実行されるように見えます。繰り返しますが、なぜですか?私はこれまでにこのようなことが起こるのを見たことがありません。

4

6 に答える 6

12
a = [81, 82, 83]
b = a
print(a is b) #prints True

これは実際にここで起こることです:

ここに画像の説明を入力

そして次のようなもののために:

a = [81,82,83]
b = [81,82,83]

print(a is b) # False

print(a == b)  #True, as == only checks value equality

ここに画像の説明を入力

In [24]: import sys

In [25]: a=[1,2,3]

In [26]: sys.getrefcount(a) #number of references to [1,2,3] are 2
Out[26]: 2

In [27]: b=a       #now b also points to [1,2,3]

In [28]: sys.getrefcount(a)   # reference to [1,2,3] got increased by 1,
                              # as b now also points to [1,2,3]
Out[28]: 3

In [29]: id(a)
Out[29]: 158656524      #both have the same id(), that's why "b is a" is True

In [30]: id(b)
Out[30]: 158656524

copyモジュールを使用する場合:

In [1]: a=[1,2,3]

In [2]: b=a

In [3]: id(a),id(b)        
Out[3]: (143186380, 143186380)   #both point to the same object

In [4]: b=a[:]                #now use slicing, it is equivalent to b=copy.copy(a)
                              # or b= list(a)    

In [5]: id(a),id(b)
Out[5]: (143186380, 143185260)     #as expected both now point to different objects
                                   # so now changing one will not affect other

In [6]: a=[[1,2],[3,4]]          #list of lists

In [7]: b=a[:]                   #use slicing

In [8]: id(a),id(b)            #now both point to different object as expected
                               # But what about the internal lists?
Out[8]: (143184492, 143186380)

In [11]: [(id(x),id(y)) for (x,y) in zip(a,b)]   #so internal list are still same objects
                                                 #so doing a[0][3]=5, will changes b[0] too
Out[11]: [(143185036, 143185036), (143167244, 143167244)]

In [12]: from copy import deepcopy            #to fix that use deepcopy

In [13]: b=deepcopy(a)

In [14]: [(id(x),id(y)) for (x,y) in zip(a,b)]    #now internal lists are different too
Out[14]: [(143185036, 143167052), (143167244, 143166924)]

詳細については:

In [32]: def func():
   ....:     a=[1,2,3]
   ....:     b=a
   ....:     
   ....:     

In [34]: import dis

In [35]: dis.dis(func)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               2 (2)
              6 LOAD_CONST               3 (3)
              9 BUILD_LIST               3
             12 STORE_FAST               0 (a)   #now 'a' poits to [1,2,3]

  3          15 LOAD_FAST                0 (a)    #load the object referenced by a
             18 STORE_FAST               1 (b)    #store the object returned by a to b 
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE        

In [36]: def func1():
   ....:     a=[1,2,3]
   ....:     b=[1,2,3]
   ....:     
   ....:     

In [37]: dis.dis(func1)      #here both a and b are loaded separately
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               2 (2)
              6 LOAD_CONST               3 (3)
              9 BUILD_LIST               3
             12 STORE_FAST               0 (a)

  3          15 LOAD_CONST               1 (1)
             18 LOAD_CONST               2 (2)
             21 LOAD_CONST               3 (3)
             24 BUILD_LIST               3
             27 STORE_FAST               1 (b)
             30 LOAD_CONST               0 (None)
             33 RETURN_VALUE   
于 2012-10-02T11:24:14.867 に答える
5

そうするとき、名前をリストオブジェクトにa = [1, 2, 3]バインドしています。aを行うと、名前が何であれ、この場合はリストオブジェクトにb = aバインドされます。エルゴ、それらは同じです...オブジェクトは複数の名前を持つことができます。Python Data Modelを読む価値があります。ba

listobj のコピーを作成したい場合は、b = a[:]slice を使用して浅いコピーを作成するかcopy.copy、浅いコピー (任意のオブジェクトで動作するはずです)、またはcopy.deepcopy奇妙なことに - 深いコピーを作成することができます。

また、短い文字列/小さな整数をキャッシュする CPython で驚くべきことに気付くでしょう...

>>> a = 4534534
>>> b = a
>>> a is b
True
>>> b = 4534534
>>> a is b
False
>>> a = 1
>>> b = a
>>> a is b
True
>>> b = 1
>>> a is b
True
于 2012-10-02T11:34:52.220 に答える
1

リストが同じように機能するかどうかはわかりませんが、浅いコピーと深いコピーに関するnumpy.array()チュートリアルからこれを見てください:http ://www.scipy.org/Tentative_NumPy_Tutorial#head-1529ae93dd5d431ffe3a1001a4ab1a394e70a5f2

a = b同じオブジェクトへの新しい参照を作成するだけです。実際のコピーを取得するには、リストオブジェクトにリンクのディープコピーの例に似たものがあることがわかりますb = a.copy()。次に、同じ値を持つ2つの別々のオブジェクトへの2つの参照があると言うことができます。

=また、ほとんどのオブジェクト指向言語は、新しいオブジェクトではなく、新しい参照を作成するだけで、このように機能すると思います。

于 2012-10-02T11:30:03.903 に答える
1

それらは実際には同じオブジェクトを参照しています。

これを試して:

a = [1,2,3]
b = a
print b is a
b[0] = 0
print b is a

aとbの両方が変更され、まだ互いに同じであることがわかります。

于 2012-10-02T11:21:55.487 に答える
1

このコードは True を出力します。なんで?

なぜならb is a

「is」は、2 つの変数が同じオブジェクトを指している場合にのみ True を返します

彼らが同じオブジェクトに名前を付ける場合。「指し示す」は、プログラミングのはるかに低いレベルのモデルをほのめかす下品な用語です。

この場合、それらは同じ値を持つ異なるオブジェクトです。

いいえ、そうではありません。

Python では、 「現在名前が付けられているものの名​​前ではなくなり、現在名前が付けられているものの名​​前になるb = a」ことを意味します。同じオブジェクト。コピーではありません。ba

Python では、物事が暗黙的にコピーされることはありません。

[3, 2, 1] [3, 2, 1] を出力します。インタプリタに関する限り、それらは同じオブジェクトのようです。

彼らがいるからです。

また、b に対する操作は自動的に a に対して実行されます。

それらは同じオブジェクトだからです。

繰り返しますが、なぜですか?

繰り返しますが、彼らはそうだからです。

...あたかもすべての明白なテストが動作を確認することを考えているようですが、すべてのテストがそれと矛盾する場合は、核となる仮定を拒否することを拒否します. .

私はこれまでにこのようなことが起こるのを見たことがありません。

Python では常にこのように動作していたので、これまで Python でこのようなことをテストしたことがないはずです。プログラミング言語の中でもそれほど奇妙ではありません。Java はプリミティブ型ではないすべてのものに対して同じことを行い、C# はクラス (参照型) に対して同じことを行いますが、構造体 (値型) に対して明らかに期待されることを行います。これは「参照セマンティクス」と呼ばれるもので、決して新しいアイデアではありません。

于 2012-10-02T12:17:34.843 に答える
0
a = [1,2,3]
b = a
print b is a

同じへの参照を比較していlistます。次の場合:

a = [1,2,3]
b = [1,2,3]
print b is a

Falseを取得する必要があります。

于 2012-10-02T11:22:19.600 に答える