2017-12-26 12 views
0

Python 3.6.2には、整数値のidの代入に奇妙な動作があります。Int値に対する奇妙なPython IDの割り当て==>不一致 'is' operation

[-5、256]の範囲の任意の整数に対して、与えられた値が割り当てられた変数には、同じ値を持つ他の変数と同じIDが割り当てられます。この効果は以下で見ることができる。

>>> a, b = -5, -5 
>>> id(a), id(b) 
(1355597296, 1355597296) 
>>> a, b = -6, -6 
>>> id(a), id(b) 
(2781041259312, 2781041260912) 

実際には、IDのペアアクションで見て、あなただけの私が話している範囲内の番号とIDを出力し、この簡単なプログラムを実行することができます...

for val in range(-6, 258): 
    print(format(val, ' 4d'), ':', format(id(val), '11x')) 

この範囲外の値を持つ他の変数を追加すると、Pythonインタプリタ内の境界条件(つまり、-6と257)の値の変更値が表示されますが、ここでは値は決してありません。

これは、Pythonが一見、任意の数値の範囲で値を保持する変数のアドレスをハードコードすることを意味しています(少なくとも私に)。

実際には、これは初心者のための通常の操作範囲内でIDの割り当てが同じであるため、初心者のPython学習者にとっては少し危険です。問題を起こす可能性のあるロジックを使用する傾向があります、それは一見...動作し、理にかなっているにもかかわらず、

一つの可能​​性のある問題インクリメント番号印刷される可能性があります(少し奇妙ではあるが):ない標準Python的な方法でも、

a = 0 
b = 10 
while a is not b: 
    a = a + 1 
    print(a) 

このロジックをbが静的に定義された数の範囲内にある限り[ - -5。 256]

しかし、この範囲からbを上げると、同じ奇妙な動作が見られます。この場合、実際には無限ループにコードがスローされます。

値を比較するための 'is'を使用することは本当に良い考えではないことがわかりますが、これは 'is'演算子を使用すると一貫性のない結果をもたらし、言語に新しいユーザーにとってはすぐにはわかりません。このメソッドを間違って使用した新しいプログラマーにとっては特に混乱します。

だから私の質問は...
A)なぜ(Pythonはこのように動作するために書かれた)、そして
b)は、それを変更する必要がありますか?

p.s.使用可能なスクリプトの範囲を適切に示すために、私は本当に不適切なコードであるいくつかの奇妙な調整を行わなければなりませんでした。しかし、この奇妙なグリッチが存在しなければ私の方法は結果を示さないので、私はまだ議論を続けている。

for val in range(-6, 300): 
    a = int(float(val)) 
    b = int(float(val)) 
    print(format(a, ' 4d'), format(id(a), '11x'), ':',format(b, ' 4d'), format(id(b), '11x'), ':', a is b) 
    val = val + 1 

float(int(val))は、各値が新しいアドレス/ IDではなく、それがアクセスしているオブジェクトへのポインタを与えるためのPythonを強制する必要があります。

+0

これは古いトピックです。https://stackoverflow.com/questions/15171695/whats-with-the-integer-cache-inside-python – mementum

答えて

0

これはPythonの振る舞いを文書化されています

現在の実装では、-5〜256のすべての整数の整数オブジェクトの配列を保持し、あなたがその範囲内でint型を作成するときは、実際には、参照を取り戻します既存のオブジェクトに追加します。 source

これは、メモリを節約して操作を少し速くするのに役立ちます。 実装固有です。たとえば、IronPythonの範囲は-1000〜1000で、整数を再利用します。

+0

TILを参照してください。ありがとう、私はこれを見つけるためにどこを探すべきか分からなかった。 –

関連する問題