web-dev-qa-db-ja.com

dict()と{}の違いは何ですか?

だから、辞書を作りたいとしましょう。 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()関数を使用した他の多くの方法。そのため、明らかにdict()が提供するものの1つは、構文と初期化の柔軟性です。しかし、それは私が尋ねていることではありません。

dを単なる空の辞書にするとします。 d = {}d = dict()を実行するときのPythonインタープリター)の背後で何が起こっているのでしょうか?同じことをする2つの方法はありますか?{}を使用すると、 追加 dict()?の呼び出し一方のオーバーヘッドは(無視できるほど)他方のオーバーヘッドよりも大きいですか?質問は本当にまったく重要ではありませんが、それは私が答えたいと思っている好奇心です。

60
verix
>>> 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を誇示したかっただけです。 :)

71
Steven Huwig

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

>>> from timeit import timeit
>>> timeit("a = {'a': 1, 'b': 2}")
0.424...
>>> timeit("a = dict(a = 1, b = 2)")
0.889...
37
DNS

@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を見て、_{}_構文を使用して、解析時に既知である格納しているアイテムの数に基づいてハッシュテーブルのサイズを事前に設定しているようです。 。

26
Matt Good

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

8

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

_{}_とdictのもう1つの違いは、dictは常に新しい辞書を(内容が静的であっても)割り当てるのに対し、_{}_はalwaysしない(-を参照) mgoodの答え いつ、なぜ):

_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 

これを利用するかどうかを提案するのではなく、特定の状況に応じて、それを指摘するだけです。 (オペコードを理解していれば、おそらく disassembly からも明らかです)。

6

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

dict( generator which yields (key,value) pairs )
dict( list of (key,value) pairs )
3
peufeu

面白い使い方:

def func(**kwargs):
      for e in kwargs:
        print(e)
    a = 'I want to be printed'
    kwargs={a:True}
    func(**kwargs)
    a = 'I dont want to be printed'
    kwargs=dict(a=True)
    func(**kwargs)

出力:

I want to be printed
a
1
Montelin