2016-11-22 4 views
5

次のコードは、指定された出力を生成します。__sizeof__ strは、その文字列を含むタプル__sizeof__より大きい

import sys 

print('ex1:') 
ex1 = 'Hello' 
print('\t', ex1.__sizeof__()) 

print('\nex2:') 
ex2 = ('Hello', 53) 
print('\t', ex2.__sizeof__()) 

出力:

ex1: 
    54  
ex2: 
    40 

なぜ__sizeof__()印刷小さい結果第二の要素が考慮されていますか?出力は大きくないはずですか? this answerからsys.getsizeof()を使用しなければならないことがわかりましたが、それでも動作は奇妙に見えます。私はPython 3.5.2を使用しています。

また、が指摘されているように、'Hello'('Hello',)よりも多くのメモリを占めており、これはtupleです。どうしてこれなの?

+0

最初のオブジェクトはタプルではなく、かっこ内の文字列です。 – Kasramvd

答えて

13

これが原因tupleオブジェクト(と私はかなり確信している文字列から除くすべてのコンテナが)の大きさを算出することで、むしろ、それぞれの内容の実際のサイズを含むことにより、そのサイズないを評価するが、という事実によるものであり、 PyObjectへのポインタに含まれる要素の倍数。つまり、(generic)PyObjectへのポインタを保持しており、それがその全体のサイズに寄与しています。

これはData Model chapter of the Python Referenceマニュアルで示唆されています

一部のオブジェクトが他のオブジェクトへの参照を含まれています。これらはコンテナと呼ばれます。コンテナの例はタプル、リスト、辞書です。参照はコンテナの値の一部です。

(。私は言葉の参照を強調しています)

In PyTupleTypetupleタイプに関する情報が含まれている構造体を、我々はtp_itemsizeフィールドは、その値としてsizeof(PyObject *)を持っていることを参照してください。

PyTypeObject PyTuple_Type = { 
    PyVarObject_HEAD_INIT(&PyType_Type, 0) 
    "tuple", 
    sizeof(PyTupleObject) - sizeof(PyObject *), 
    sizeof(PyObject *), // <-- sizeof pointer to PyObject's 
32

ビットを構築しsizeof(PyObject *)を有する64ビットは、Pythonのビルド8バイトに等しい。

これは、tupleインスタンスに含まれるアイテムの数で乗算される値です。私たちはobject_sizeを見てみると、tuple sが(object.__sizeof__ is tuple.__sizeof__を調べる)objectから継承__sizeof__方法は、我々は明らかに、これを参照してください。

static PyObject * 
object_sizeof(PyObject *self, PyObject *args) 
{ 
    Py_ssize_t res, isize; 

    res = 0; 
    isize = self->ob_type->tp_itemsize; 
    if (isize > 0) 
     res = Py_SIZE(self) * isize; // <-- num_elements * tp_itemsize 
    res += self->ob_type->tp_basicsize; 

    return PyLong_FromSsize_t(res); 
} 

は他のマクロである、Py_SIZE(self)を乗じてどのようisizetp_itemsizeから入手)を参照してくださいob_sizeをつかみ、の中にある要素の数がであることを示します。タプルのサイズ

t[0].__sizeof__()   # 5169 

:の大きさを持つその中

t = ("Hello" * 2 ** 10,) 

要素を持つ:我々はタプルインスタンス内のやや大きな文字列を作成しても、なぜ、

です例:

t.__sizeof__()   # 32 

は、単純に"Hello"のものと同じです。

t2 = ("Hello",) 
t[0].__sizeof__()   # 54 
t2.__sizeof__()   # 32 Tuple size stays the same. 

文字列の場合、個々の文字はそれぞれstr.__sizeof__から返される値を大きくします。これは、tupleがポインタのみを格納するという事実と共に、"Hello"がそれを含んでいるタプルよりも大きいという誤った印象を与えます。

完全性のために、これを計算するのはunicode__sizeof__です。実際には、文字列の長さに文字サイズ(文字が12、および4バイトの文字に依存する)を乗算するだけです。

タプルでは得られない唯一の理由は、基本サイズ(tb_basicsizeで示される)がsizeof(PyTupleObject) - sizeof(PyObject *)と表示されている理由です。これは返される全体サイズから8バイトを流します。私はこれについての説明はまだ見つけていない(まだ)。

+1

別のトップの答えが、私はcpythonのタグがこれらのpython内部の質問で無視されているのだろうかと思う。 –

+0

私は自分自身が@Chris_Randsだろうと思った。しばらく前に、タグのトップQを読み飛ばすと、ほとんどの人が 'python-internals'と' CPython'の仕組みを同一視していることに気づきました。 –

関連する問題