PyCharmを使用して、dict literalを変換することを提案しています
d = {
'one': '1',
'two': '2',
}
dictコンストラクター:
d = dict(one='1', two='2')
これらの異なるアプローチはいくつかの重要な点で異なりますか?
(この質問を書いている間、dict()
を使用すると数値キーを指定することは不可能に思えます。_d = {1: 'one', 2: 'two'}
は可能ですが、明らかにdict(1='one' ...)
は不可能です。
最も明らかな違いを指摘されたと思います。それとは別に、
最初のものはdict
を検索する必要がないため、少し速くなります
2番目はlocals()
でdict
を検索してからglobals()
を検索し、組み込み関数を見つけるため、たとえばdict
と呼ばれるローカルを定義することで動作を切り替えることができます。
リテラルは、汎用CALL_FUNCTIONではなく最適化されたBUILD_MAPおよびSTORE_MAPオペコードを使用するため、はるかに高速です。
> python2.7 -m timeit "d = dict(a=1, b=2, c=3, d=4, e=5)"
1000000 loops, best of 3: 0.958 usec per loop
> python2.7 -m timeit "d = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5}"
1000000 loops, best of 3: 0.479 usec per loop
> python3.2 -m timeit "d = dict(a=1, b=2, c=3, d=4, e=5)"
1000000 loops, best of 3: 0.975 usec per loop
> python3.2 -m timeit "d = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5}"
1000000 loops, best of 3: 0.409 usec per loop
Python 3.2でもほとんど同じように見えます。
Gnibblerが指摘したように、最初のものはdict
をルックアップする必要がありません。
>>> def literal():
... d = {'one': 1, 'two': 2}
...
>>> def constructor():
... d = dict(one='1', two='2')
...
>>> import dis
>>> dis.dis(literal)
2 0 BUILD_MAP 2
3 LOAD_CONST 1 (1)
6 LOAD_CONST 2 ('one')
9 STORE_MAP
10 LOAD_CONST 3 (2)
13 LOAD_CONST 4 ('two')
16 STORE_MAP
17 STORE_FAST 0 (d)
20 LOAD_CONST 0 (None)
23 RETURN_VALUE
>>> dis.dis(constructor)
2 0 LOAD_GLOBAL 0 (dict)
3 LOAD_CONST 1 ('one')
6 LOAD_CONST 2 ('1')
9 LOAD_CONST 3 ('two')
12 LOAD_CONST 4 ('2')
15 CALL_FUNCTION 512
18 STORE_FAST 0 (d)
21 LOAD_CONST 0 (None)
24 RETURN_VALUE
これらの2つのアプローチは、Pythonの字句規則が干渉する場合を除いて、同じ辞書を生成します。
辞書リテラルはもう少し明らかに辞書であり、任意の種類のキーを作成できますが、キー名を引用符で囲む必要があります。一方、何らかの理由で必要な場合は、キーに変数を使用できます。
a = "hello"
d = {
a: 'hi'
}
dict()
コンストラクターは、入力の形式がさまざまであるため、柔軟性が向上します。たとえば、ペアのイテレータを提供することができ、キー/値のペアとしてそれらを扱います。
PyCharmが1つのフォームを他のフォームに変換する理由を私は知りません。
python 3.4 + pycharmとの大きな違いは、キーの数が256を超えると、dict()コンストラクターが「構文エラー」メッセージを生成することです。
今はdictリテラルを使用することを好みます。
python 2.7チュートリアルから:
中括弧のペアは、空の辞書{}を作成します。中括弧内にkey:valueペアのコンマ区切りリストを配置すると、初期のkey:valueペアが辞書に追加されます。これは、辞書が出力に書き込まれる方法でもあります。
tel = {'jack': 4098, 'sape': 4139}
data = {k:v for k,v in Zip(xrange(10), xrange(10,20))}
一方:
Dict()コンストラクターは、タプルとして保存されたキーと値のペアのリストから直接辞書を作成します。ペアがパターンを形成するとき、リスト内包表記はキーと値のリストをコンパクトに指定できます。
tel = dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) {'sape': 4139, 'jack': 4098, 'guido': 4127}
data = dict((k,v) for k,v in Zip(xrange(10), xrange(10,20)))
キーが単純な文字列の場合、キーワード引数を使用してペアを指定する方が簡単な場合があります。
dict(sape=4139, guido=4127, jack=4098)
>>> {'sape': 4139, 'jack':4098, 'guido': 4127}
したがって、{}とdict()は両方とも辞書を作成しますが、辞書データの初期化の方法は少し異なります。
Dict継承クラス、追加メソッドを持つカスタムdictクラスを作成するdictリテラルはありません。このような場合、カスタムdictクラスコンストラクターを使用する必要があります。次に例を示します。
class NestedDict(dict):
# ... skipped
state_type_map = NestedDict(**{
'owns': 'Another',
'uses': 'Another',
})
Dictリテラルd = {'one': '1'}
は、物事の値を割り当ててdict()
コンストラクターに送信するのではなく、はるかに読みやすい定義データであることがわかりました。
その一方で、現代ではpython 2.7+がセットを作成するd = {'one', '1'}
としてdictリテラルを誤って入力するのを見てきました。
それにもかかわらず、私はそれがより読みやすく、個人的な好みだと思うので、私はまだセットリテラルを使用することを好みます。
dict()リテラルは、他の何か(Pythonなし)から値を貼り付ける場合に便利です。たとえば、環境変数のリストです。あなたがbashファイルを持っているなら、言う
FOO='bar'
CABBAGE='good'
その後、簡単にdict()
リテラルに貼り付けてコメントを追加できます。また、反対のことを簡単に行うことができ、他の何かにコピーします。一方、{'FOO': 'bar'}
構文は、pythonおよびjsonに非常に固有です。したがって、jsonを頻繁に使用する場合は、二重引用符付きの{}
リテラルを使用することをお勧めします。
また、演算子に一致するトークンはコンストラクター構文、つまりダッシュ化されたキーでは使用できないという事実も考慮してください。
>>> dict(foo-bar=1)
File "<stdin>", line 1
SyntaxError: keyword can't be an expression
>>> {'foo-bar': 1}
{'foo-bar': 1}