dict() と {} の違いは何ですか?
-
21-08-2019 - |
質問
それで、辞書を作りたいとします。呼んでみましょう 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
ただの空の辞書。実行すると、Python インタープリターの舞台裏で何が起こっているのか d = {}
対 d = dict()
?同じことを行うのに 2 つの方法があるだけでしょうか?を使用します {}
持っています 追加 の呼び出し dict()
?一方のオーバーヘッドは他方よりも (無視できるほどでも) 大きくなりますか?この質問は実際にはまったく重要ではありませんが、答えてみたいと思う好奇心です。
解決
>>> 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
辞書()は明らかにいくつかのCビルトインです。本当にスマートまたは専用の人が(私ではない)インタプリタソースを見て、より多くのあなたが言うことができます。私はちょうどdis.disを誇示したかったです。 :)
他のヒント
のパフォーマンスが行く限ります:
>>> from timeit import timeit
>>> timeit("a = {'a': 1, 'b': 2}")
0.424...
>>> timeit("a = dict(a = 1, b = 2)")
0.889...
@Jacob:そこのオブジェクトが割り当てられているかの違いはあるが、彼らは、コピー・オン・ライトされていません。 Pythonは(それがいっぱいになるまで)、それはすぐに辞書オブジェクトを割り当てることができ、固定サイズの「フリーリスト」を割り当てます。 {}
構文(またはPyDict_New
にC呼び出し)を介して割り当てられた辞書は、このフリーリストから来ることができます。辞書が参照されなくなった場合、それはフリーリストに返されません取得し、(フィールドが最初にリセットされますが)そのメモリ・ブロックを再利用することができます。
この最初の辞書はすぐにフリーリストに返されると、次はそのメモリ空間を再利用します。
>>> id({})
340160
>>> id({1: 2})
340160
あなたが参照を保持する場合は、次の辞書は次の空きスロットから来るます:
>>> x = {}
>>> id(x)
340160
>>> id({})
340016
しかし、我々はその辞書への参照を削除し、再度、そのスロットを解放することができます:
>>> del x
>>> id({})
340160
{}
構文がバイトコードで処理されるので、は、上述したこの最適化を使用することができます。一方dict()
は、通常のクラスのコンストラクタのように処理され、Pythonは上記のフリー・リストのような容易に予測可能なパターンに従わない汎用のメモリアロケータを使用します。
また、{}
構文で、Pythonの2.6からcompile.cを見て、それが解析時に知られている記憶手段だアイテムの数に基づいて、ハッシュテーブルにプリ大きそうです。
基本的には、{}構文であり、言語やバイトコードレベルで処理されます。辞書()は、より柔軟な初期化構文でだけ別の組み込みです。その辞書に注意してください()のみ2.xシリーズの途中で添加した。
アップデート:ご回答ありがとうございます。コピーオンライトに関する推測を削除しました。
もう1つの違いは、 {}
そして dict
それは? dict
常に新しい辞書を割り当てます (内容が静的であっても)。 {}
しません いつも そうしてください(参照 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
私はこれを利用するかどうかを提案しているのではなく、特定の状況によって異なります。ただそれを指摘しているだけです。(それはおそらく次のことからも明らかです) 分解 オペコードを理解していれば)。
辞書()あなたはイテラブルから辞書を作成する場合と同様に、使用されます:
dict( generator which yields (key,value) pairs )
dict( list of (key,value) pairs )
おかしい用法ます:
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
空のセットを作成するために、我々は、その前にキーワードセットを使用する必要があります
すなわちこれはdictsのように一つだけの花ブラケットを空の辞書を作成することができます空のセットを作成しますset()
タグの例で行くことができます
print isinstance({},dict)
True
print isinstance({},set)
False
print isinstance(set(),set)
True