web-dev-qa-db-ja.com

不変文字列のIDの変更について

タイプid(python 2.7))のオブジェクトのstrについて何かが私を困惑させます。strタイプは不変なので、作成された後は常に同じidになることを期待してください。自分の言い回しはあまり上手ではないので、代わりに入力シーケンスと出力シーケンスの例を投稿します。

_>>> id('so')
140614155123888
>>> id('so')
140614155123848
>>> id('so')
140614155123808
_

その間、それは常に変化します。ただし、その文字列を指す変数を指定すると、状況が変化します。

_>>> so = 'so'
>>> id('so')
140614155123728
>>> so = 'so'
>>> id(so)
140614155123728
>>> not_so = 'so'
>>> id(not_so)
140614155123728
_

したがって、変数がその値を保持すると、IDがフリーズするように見えます。実際、_del so_および_del not_so_の後で、id('so')の出力が再び変化し始めます。

これはnot(小さい)整数の場合と同じ動作です。

不変性と同じidの間に実際の関係はないことを知っています。それでも、私はこの行動の原因を解明しようとしています。私はpythonの内部に精通している誰かが私ほど驚かないと信じているので、私は同じ点に到達しようとしています...

更新

異なる文字列で同じことを試みると、異なる結果が得られました...

_>>> id('hello')
139978087896384
>>> id('hello')
139978087896384
>>> id('hello')
139978087896384
_

今それはis等しい...

43
Bach

この動作は、Pythonインタラクティブシェルに固有です。pyファイルに次のコードを追加した場合:

print id('so')
print id('so')
print id('so')

それを実行すると、次の出力が表示されます。

 2888960 
 2888960 
 2888960 

CPythonでは、文字列リテラルは定数として扱われ、上記のスニペットのバイトコードで確認できます。

  2           0 LOAD_GLOBAL              0 (id)
              3 LOAD_CONST               1 ('so')
              6 CALL_FUNCTION            1
              9 PRINT_ITEM          
             10 PRINT_NEWLINE       

  3          11 LOAD_GLOBAL              0 (id)
             14 LOAD_CONST               1 ('so')
             17 CALL_FUNCTION            1
             20 PRINT_ITEM          
             21 PRINT_NEWLINE       

  4          22 LOAD_GLOBAL              0 (id)
             25 LOAD_CONST               1 ('so')
             28 CALL_FUNCTION            1
             31 PRINT_ITEM          
             32 PRINT_NEWLINE       
             33 LOAD_CONST               0 (None)
             36 RETURN_VALUE  

same定数(つまり、同じ文字列オブジェクト)が3回読み込まれるため、IDは同じです。

4
arshajii

最初の例では、文字列'so'の新しいインスタンスが毎回作成されるため、IDが異なります。

2番目の例では、文字列を変数にバインドし、Pythonは文字列の共有コピーを維持できます。

1
mhawke

動作を理解するより簡単な方法は、次の データ型と変数 を確認することです。

セクション「文字列の特殊性」では、例として特殊文字を使用して質問を説明します。

したがって、Pythonはインターン文字列が保証されていませんが、同じ文字列を頻繁に再利用するため、isは誤解を招く可能性があります。idまたはis

これを実証するために、少なくともPython 2.6で新しい文字列を強制する方法を発見しました:

>>> so = 'so'
>>> new_so = '{0}'.format(so)
>>> so is new_so 
False

そしてもう少しPython探査:

>>> id(so)
102596064
>>> id(new_so)
259679968
>>> so == new_so
True
0
Aaron Hall