[解決済み] Python文字列インターン
質問
この質問は実際には何の役にも立ちませんが、Pythonがどのように文字列のインターリングを行うのかに興味があります。私は以下のことに気づきました。
>>> "string" is "string"
True
これは予想通りです。
こんなこともできるんですね。
>>> "strin"+"g" is "string"
True
と、なかなか気が利いてますね〜。
でも、こんなことはできません。
>>> s1 = "strin"
>>> s2 = "string"
>>> s1+"g" is s2
False
なぜPythonは
s1+"g"
を評価し、それが
s2
と同じであることに気づき、同じアドレスを指定するのでしょうか?この最後のブロックでは実際に何が起こっているのでしょうか?
False
?
どのように解決するのですか?
これは実装に依存しますが、インタープリタはおそらくコンパイル時の定数をインターセプトしていますが、実行時の式の結果はインターセプトしていません。
以下では、CPython 3.9.0+を使用しています。
2番目の例では、式
"strin"+"g"
はコンパイル時に評価され、次のように置き換えられます。
"string"
. これにより、最初の2つの例は同じ振る舞いをするようになります。
バイトコードを調べると、全く同じであることがわかります。
# s1 = "string"
1 0 LOAD_CONST 0 ('string')
2 STORE_NAME 0 (s1)
# s2 = "strin" + "g"
2 4 LOAD_CONST 0 ('string')
6 STORE_NAME 1 (s2)
このバイトコードは、(上記の後に数行表示される) で取得されたものです。
import dis
source = 's1 = "string"\ns2 = "strin" + "g"'
code = compile(source, '', 'exec')
print(dis.dis(code))
3つ目の例は、実行時の連結を伴うもので、その結果は自動的にインターネイトされません。
# s3a = "strin"
3 8 LOAD_CONST 1 ('strin')
10 STORE_NAME 2 (s3a)
# s3 = s3a + "g"
4 12 LOAD_NAME 2 (s3a)
14 LOAD_CONST 2 ('g')
16 BINARY_ADD
18 STORE_NAME 3 (s3)
20 LOAD_CONST 3 (None)
22 RETURN_VALUE
このバイトコードは、(上記の前にさらに数行表示され、それらの行は上記で与えられたバイトコードの最初のブロックと全く同じです)で取得されました。
import dis
source = (
's1 = "string"\n'
's2 = "strin" + "g"\n'
's3a = "strin"\n'
's3 = s3a + "g"')
code = compile(source, '', 'exec')
print(dis.dis(code))
もしあなたが手動で
sys.intern()
を手動で実行した場合、前と同じオブジェクトが得られます。
>>> import sys
>>> s3a = "strin"
>>> s3 = s3a + "g"
>>> s3 is "string"
False
>>> sys.intern(s3) is "string"
True
また、Python 3.9では、上記の最後の2つのステートメントに対して警告が表示されます。
SyntaxWarning: "is" がリテラルで表示されました。これは "==" のことでしょうか?
関連
-
[解決済み] JavaScriptで文字列が部分文字列を含むかどうかを確認する方法は?
-
[解決済み] C#のStringとstringの違いは何ですか?
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] バイトを文字列に変換する
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] Pythonで文字列の部分文字列を取得するにはどうすればよいですか?
-
[解決済み】JavaScriptで文字列の出現箇所をすべて置換する方法
-
[解決済み】Pythonに三項条件演算子はありますか?
-
[解決済み] Pandasの'Freq'タグにはどのような値が有効ですか?
-
[解決済み] あるオブジェクトが数であるかどうかを確認する、最もパイソン的な方法は何でしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 2つの線分が交差しているかどうかを確認するにはどうすればよいですか?
-
[解決済み] PILからopenCVフォーマットへの変換
-
[解決済み] 小数点以下1桁を取得する[重複]。
-
[解決済み] Pythonのインスタンス変数とクラス変数
-
[解決済み] DataFrameに日付間の日数カラムを追加する pandas
-
[解決済み] ファブリック経由でデプロイユーザとしてvirtualenvを有効化する
-
[解決済み] python-requests モジュールからのすべてのリクエストをログに記録します。
-
[解決済み] オブジェクトのリストに特定の属性値を持つオブジェクトが含まれているかどうかをチェックする
-
[解決済み] if 節の終了方法
-
[解決済み] Pythonの検索パスを他のソースに展開する