70

では、辞書を作りたいとしましょう。と呼びますd。しかし、Python で辞書を初期化する方法は複数あります。たとえば、私はこれを行うことができます:

d = {'hash': 'bang', 'slash': 'dot'}

または私はこれを行うことができます:

d = dict(hash='bang', slash='dot')

またはこれ、不思議なことに:

d = dict({'hash': 'bang', 'slash': 'dot'})

またはこれ:

d = dict([['hash', 'bang'], ['slash', 'dot']])

そして、dict()関数を使用した他の多くの方法。したがって、明らかに提供されるものの 1 つは、dict()構文と初期化の柔軟性です。しかし、それは私が尋ねていることではありません。

d空の辞書を作成するとします。d = {}vsを実行すると、Python インタープリターの舞台裏で何が起こっているのd = dict()でしょうか? 同じことをするのは単に2つの方法ですか?using{}には の追加呼び出しがありdict()ますか? 一方のオーバーヘッドが他方より (ごくわずかでも) 多いですか? 質問は本当にまったく重要ではありませんが、私が答えたいと思っている好奇心です.

4

8 に答える 8

78
>>> def f():
...     return {'a' : 1, 'b' : 2}
... 
>>> def g():
...     return dict(a=1, b=2)
... 
>>> g()
{'a': 1, 'b': 2}
>>> f()
{'a': 1, 'b': 2}
>>> import dis
>>> dis.dis(f)
  2           0 BUILD_MAP                0
              3 DUP_TOP             
              4 LOAD_CONST               1 ('a')
              7 LOAD_CONST               2 (1)
             10 ROT_THREE           
             11 STORE_SUBSCR        
             12 DUP_TOP             
             13 LOAD_CONST               3 ('b')
             16 LOAD_CONST               4 (2)
             19 ROT_THREE           
             20 STORE_SUBSCR        
             21 RETURN_VALUE        
>>> dis.dis(g)
  2           0 LOAD_GLOBAL              0 (dict)
              3 LOAD_CONST               1 ('a')
              6 LOAD_CONST               2 (1)
              9 LOAD_CONST               3 ('b')
             12 LOAD_CONST               4 (2)
             15 CALL_FUNCTION          512
             18 RETURN_VALUE        

dict() は明らかにCの組み込みです。本当に頭の良い、または献身的な人 (私ではない) は、通訳者のソースを見て、さらに多くのことを話すことができます. dis.disを見せびらかしたかっただけです。:)

于 2009-03-19T21:25:14.607 に答える
42

パフォーマンスに関する限り:

>>> from timeit import timeit
>>> timeit("a = {'a': 1, 'b': 2}")
0.424...
>>> timeit("a = dict(a = 1, b = 2)")
0.889...
于 2009-03-19T21:41:00.827 に答える
29

@Jacob: オブジェクトの割り当て方法に違いがありますが、コピーオンライトではありません。Python は固定サイズの「空きリスト」を割り当て、そこにディクショナリ オブジェクトを (いっぱいになるまで) すばやく割り当てることができます。{}構文 (または への C 呼び出し)によって割り当てられた辞書はPyDict_New、この空きリストから取得できます。ディクショナリが参照されなくなると、フリー リストに返され、そのメモリ ブロックを再利用できます (ただし、フィールドは最初にリセットされます)。

この最初の辞書はすぐにフリー リストに返され、次の辞書はそのメモリ空間を再利用します。

>>> id({})
340160
>>> id({1: 2})
340160

参照を保持すると、次の辞書は次の空きスロットから取得されます。

>>> x = {}
>>> id(x)
340160
>>> id({})
340016

しかし、その辞書への参照を削除して、そのスロットを再び解放することができます。

>>> del x
>>> id({})
340160

構文はバイトコードで処理されるため、{}上記の最適化を使用できます。一方、dict()は通常のクラス コンストラクターのように処理され、Python は一般的なメモリ アロケーターを使用します。これは、上記の空きリストのような簡単に予測できるパターンには従いません。

また、Python 2.6 の compile.c を見ると、{}構文を使用して、解析時に既知である、格納されているアイテムの数に基づいてハッシュテーブルのサイズを事前に設定しているようです。

于 2009-03-25T12:28:03.537 に答える
9

基本的に、{} は構文であり、言語およびバイトコード レベルで処理されます。dict() は、より柔軟な初期化構文を持つ別のビルトインです。dict() は 2.x シリーズの途中でのみ追加されたことに注意してください。

于 2009-03-19T23:15:01.613 に答える
7

更新:返信ありがとうございます。コピー オン ライトに関する推測を削除しました。

と の間のもう 1 つの違いは、 (内容が静的であっても) 常に新しい辞書を割り当てることですが、常にそうする{}とは限りません(いつ、どのような理由についてはmgood の回答を参照してください)。dictdict{}

def dict1():
    return {'a':'b'}

def dict2():
    return dict(a='b')

print id(dict1()), id(dict1())
print id(dict2()), id(dict2())

生成:

$ ./mumble.py
11642752 11642752
11867168 11867456

これを利用しようとするかどうかを提案しているわけではありません。それは特定の状況に依存し、指摘しているだけです。(オペコードを理解していれば、逆アセンブルからも明らかです)。

于 2009-03-20T18:44:30.367 に答える
3

dict() は、次のように反復可能オブジェクトから辞書を作成する場合に使用されます。

dict( generator which yields (key,value) pairs )
dict( list of (key,value) pairs )
于 2011-04-29T21:50:46.820 に答える