クイズ
Pythonクイズ
文字列中に含まれる a という1文字が消費するメモリサイズは?
- 1バイト
- 2バイト
- 3バイト
- 4バイト
- わからない
こういう問いかけをSlack上でしたところ、「1. 1バイト」と答えた人が9名、「5. わからない」と答えた人が4名でした。
出題意図としては、「5. わからない」あるいは、「1. 1バイト」&「2. 2バイト」&「4. 4バイト」の3つを選択してくれたなら正解のつもりだったので、4名が正解。
選択問題出すときに、選択肢に「わからない」を入れたんだけど、答えがわからないから選んだのか、わからないが答えだから選んだかの区別がつかなくなってしまった。なお、わからないが答えでした
— Yoichi Nakayama (@yoichi22) 2021年7月1日
さらにいうと「わからない」を臆せず言えるようになる練習の意図もあったので、答えがわからないから選んだ人にも二重丸あげたい
— Yoichi Nakayama (@yoichi22) 2021年7月1日
Python: PEP-393
Python 3.3 以降における文字列の内部表現は、latin-1 or UCS-2 or UCS-4 のいずれかが用いられる。どれが用いられるかは文字列中の文字のコードポイントの最大値で決まる。256未満ならlatin-1配列(1文字1バイト)、65536未満ならUCS-2配列(1文字2バイト)、それ以外ならUCS-4配列(1文字4バイト)
CPythonの実装は
cpython/unicodeobject.c at 0d7f61ddb074659d8c18c8f5ac86a6a18e41f9e5 · python/cpython · GitHub
で、NULL終端の分も含めて (size + 1) * char_size
分のメモリを文字列格納用に確保している。
クイズの答えはpython REPL上で以下のように確認できる:
>>> import sys >>> X = "abc" >>> sys.getsizeof(X + "a") - sys.getsizeof(X) 1 >>> X = "abcあ" >>> sys.getsizeof(X + "a") - sys.getsizeof(X) 2 >>> X = "abcあ\U00029e3d" >>> X 'abcあ𩸽' >>> sys.getsizeof(X + "a") - sys.getsizeof(X) 4 >>>
他の言語処理系では
ついでにPython以外だとどうなのか調べてみたら、いろいろあることがわかった。
Rubyはバイト列とエンコーディングの組み合わせで文字列を表現しているとのこと。
.NET は UTF-16
Java は UTF-16 だけど、Java9以降では1文字1バイトに収まる時はlatin-1で表現しているとのこと。知らなかった。
Goの string は UTF-8