すべてのPythonオブジェクトは、いくつかのフィールドを持つC構造体として実装されています。参照カウントとオブジェクトの型へのポインタを含む16バイトのheaderは、常にこの構造体に存在します。これは少なくとも私の質問が制限されている64bitのCPython 3.xの場合です。CPythonオブジェクトの基礎となるC構造体表現の出力
私は、学問目的で楽しんで、渡されたオブジェクトobj
のこの基礎となるstruct
をプリントアウトする関数print_object(obj)
を探しています。
最も単純なPythonオブジェクトはおそらくfloat
で、これは前述のヘッダーに追加されたC double
です。このような単純なケースでは、私はとstruct
モジュール使用して自分自身のように関数を記述することができました:本質的には
import collections, ctypes, struct, sys
header_fields = ['refcount', 'typeptr']
Float = collections.namedtuple('Float', header_fields + ['value'])
def print_object(obj):
ptr = id(obj)
size = sys.getsizeof(obj)
byterep = ctypes.string_at(ptr, size)
header = struct.unpack('qq', byterep[:16])
if isinstance(obj, float):
obj_struct = Float(*header, *struct.unpack('d', byterep[16:]))
elif isinstance(obj, int):
...
print(obj_struct)
# Try it out
a = 1.23
print_object(a)
print('The typeptr should be equal to', id(float))
print('\nNow the refcount should have increased by 1:')
b = a
print_object(a)
を、この関数は、オブジェクトの基本的なメモリを読み取り、C struct
などのコピーを作成しますPython namedtuple
は、Python自体を効果的に再表現しています。コードはPython 3.5以降で動作するはずです。
フロート(参照カウント=を:それは
フロート(参照カウント= 5、typeptr = 140429307606720、値= 1.23)
typeptrすぐ参照カウントは1だけ増加しているべきである140429307606720に等しくなければならない印刷します6、typeptr = 140429307606720、値= 1.23)
上記print_object
関数はfloat
のための素晴らしい働き、同じ方法は、(I仮定?)他のすべてのタイプに拡張することができます。そこにあるライブラリ(あるいはおそらくPythonのstadardライブラリ)にもこのような機能が含まれていますか?
さて、カスタムメイドの 'class'を無視しましょう。 'struct'のサイズに関しては、' sys.getsizeof(obj) 'が提供するものとまったく同じではありませんか? –
@jmd_dk:いいえ。これには、オブジェクトに属していて実際に構造体の一部ではない他のメモリ(リストのバッキングバッファなど)が含まれます。 – user2357112