sys
のgetsizeof()
をいじってみたところ、False
(または_0
_)はTrue
(または_1
_)。何故ですか?
_import sys
print("Zero: " + str(sys.getsizeof(0)))
print("One: " + str(sys.getsizeof(1)))
print("False: " + str(sys.getsizeof(False)))
print("True: " + str(sys.getsizeof(True)))
# Prints:
# Zero: 24
# One: 28
# False: 24
# True: 28
_
実際、他の数値(複数の数字で構成されるものもある)は28バイトです。
_for n in range(0, 12):
print(str(n) + ": " + str(sys.getsizeof(n)))
# Prints:
# 0: 24
# 1: 28
# 2: 28
# 3: 28
# 4: 28
# 5: 28
# 6: 28
# 7: 28
# 8: 28
# 9: 28
# 10: 28
# 11: 28
_
さらに:sys.getsizeof(999999999)
も28バイトです!ただし、sys.getsizeof(9999999999)
は32です。
どうしたの?ブール値True
とFalse
がそれぞれ_0
_と_1
_に内部的に変換されると思いますが、なぜ他の小さい整数とサイズがゼロでないのですか?
副次的な質問:これは、Python(3)がこれらの項目を表す方法に固有ですか、それともOSで数字がどのように表示されるか一般的にですか?
Python int
の値は任意のサイズであることを忘れないでください。それはどのように機能しますか?
まあ、CPythonでは1 intは、4バイトのチャンクの配列を持つ_PyLong_Object
_で表されます2、それぞれ30ビットを保持3 数の価値。
0
_はチャンクをまったく取りません。1
_-_(1<<30)-1
_は1つのチャンクを取ります。1<<30
_-_(1<<60)-1
_は2つのチャンクを取ります。等々。
これは少し単純化されすぎています。詳細については、ソースの _longintrepr.h
_ を参照してください。
Python 2には、int
とlong
の2つの型があります。 int
は、C 32ビット符号付き整数で表されます4 チャンクの配列ではなく、ヘッダーに直接埋め込まれます。 long
はPython 3 int
に似ています。
_0L
_、_1L
_などを使用して同じテストを実行し、long
値を明示的に要求すると、Python 3と同じ結果が得られますが、L
接尾辞、32ビットに収まるリテラルはint
を提供し、大きすぎるリテラルのみがlong
sを提供します。5 (つまり、_(1<<31)-1
_はint
ですが、_1<<31
_は2チャンクlong
です。)
1.別の実装では、これは当てはまらない場合があります。 IIRC、JythonはCPythonとほぼ同じことを行いますが、IronPythonはC#の「bignum」実装を使用します。
2.なぜ32ビットではなく30ビットなのですか?主に、2つの "桁"のビット数が_**
_で割り切れると仮定できる場合、pow
および_10
_の実装がより簡単で高速になるためです。
3. C "struct hack" を使用します。技術的には、_Py_LongObject
_は28バイトですが、_Py_LongObject
_を割り当てる人はいません。それらは24、28、32、36などのバイトをmallocしてから_Py_LongObject *
_にキャストします。
4.実際、Python int
は、混乱を招くだけのCのlong
です。したがって、C APIには、_PyInt_FromLong
_(long
は "32ビットint"を意味する)や_PyLong_FromSize_t
_(long
は "bignum"を意味する)などの機能が満載です。
5. Python 2.xの初期のバージョンでは、int
とlong
がうまく統合されていませんでしたが、もう心配する必要はありません。