dictを初期化するための推奨構文は何ですか:中括弧リテラル{}またはdict()関数?


212

私はPythonを学ぶために少し努力していますが、一般的なコーディング標準に細心の注意を払っています。これは無意味にひねくれた質問のように思えるかもしれませんが、私は学習しながらベストプラクティスに焦点を合わせようとしているため、「悪い」習慣を習得する必要はありません。

辞書を初期化する一般的な方法は2つあります。

a = {
    'a': 'value',
    'another': 'value',
}

b = dict( 
    a='value',
    another='value',
)

「よりpythonic」と考えられているのはどれですか?どちらを使いますか?どうして?


5
どのチュートリアルを使用していますか?混乱を招く例をどこで見ましたか?
S.Lott

2
まあ、私はPythonチュートリアル、Dive into Pythonを使用しており、その後、さまざまなブログ、SO投稿、その他のGoogleリソースを使用しています。公式ドキュメントは{}かなり均一に使用しますが、dict()他の場所では多くの明示的なアプローチを目にしています。明示的な構文の利点を確認できましたが、公式ドキュメントにアプローチがないため、疑わしくなりました。これを投稿した後、私はライブラリのドキュメントを調べ、dictを初期化するためにdict明示的dictに使用する場合、キーは有効な識別子でなければならないという警告を見つけました。
daotoad

2
「dict()」は「{}」よりもどのように明示されていますか?私はあなたの混乱を理解していません。どちらも私には明白に思えます。「dict」は「明示的」であり、「{}」は明示的ではないという引用や参照を提供できますか?この違いはどこから来たと思いますか?
S.Lott

21
違いはスペルです。 dict()スペルdict-タイプの名前を使用します。中括弧({})は、句読点を使用してタイプを識別します。
daotoad

回答:


235

中かっこ。キーワード引数をdict()に渡すと、多くのシナリオで問題なく機能しますが、キーが有効なPython識別子である場合にのみマップを初期化できます。

これは機能します:

a = {'import': 'trade', 1: 7.8}
a = dict({'import': 'trade', 1: 7.8})

これは動作しません:

a =                  dict(import='trade', 1=7.8)
>> SyntaxError: invalid syntax  ^

85

最初の波括弧。そうしないと、のように奇数文字が含まれるキーで一貫性の問題が発生します=

# Works fine.
a = {
    'a': 'value',
    'b=c': 'value',
}

# Eeep! Breaks if trying to be consistent.
b = dict( 
    a='value',
    b=c='value',
)

11
これがまさに、初期化にdict()メソッドを好むかもしれない理由です。辞書のキーを有効な識別子に強制するため、たとえば** kwargsと互換性があり、キーは有効な属性名です。
RufusVS

57

最初のバージョンが望ましい:

  • すべての種類のキーで機能するため、たとえばと言うことができます{1: 'one', 2: 'two'}。2番目のバリアントは(一部の)文字列キーに対してのみ機能します。キーのタイプに応じて異なる種類の構文を使用すると、不必要な不整合が生じます。
  • より高速です:

    $ python -m timeit "dict(a='value', another='value')"
    1000000 loops, best of 3: 0.79 usec per loop
    $ python -m timeit "{'a': 'value','another': 'value'}"
    1000000 loops, best of 3: 0.305 usec per loop
  • 辞書リテラルの特別な構文が使用されることを意図していない場合、おそらく存在しません。

3

値にa ['a']またはa ['another']としてアクセスするため、最初のオプションの方が良いと思います。辞書のキーは文字列であり、文字列がそうでないふりをする理由はありません。私にとって、キーワード構文は最初は賢く見えますが、2番目の見方ではあいまいです。これは、を使用している場合にのみ意味が__dict__あり、キーワードは後でそのような属性になります。


3

参考までに、ディクショナリに属性を追加する必要がある場合(ディクショナリにアタッチされているが、キーの1つではないもの)は、2番目のフォームが必要になります。その場合、次のように、任意の文字を1つずつ持つキーで辞書を初期化できます。

    class mydict(dict): pass
    a = mydict()        
    a["b=c"] = 'value'
    a.test = False

2

時にはdict()良い選択です:

a=dict(zip(['Mon','Tue','Wed','Thu','Fri'], [x for x in range(1, 6)]))

mydict=dict(zip(['mon','tue','wed','thu','fri','sat','sun'],

[random.randint(0,100)for x for range(0,7)]))


2
これをよりよく行うことができる列挙関数があります。さらに言えば、ここであなたがしていることをよりうまく行うことができるEnumタイプがあります。また、これは実際には質問に対する回答ではありません。
dusktreader

2

ほとんどの場合、中括弧を使用します。ただし、テストを記述している場合は、キーワードのパッキング/アンパッキングを行います。これらの場合、変更する必要がないため、dict()の方がはるかに保守しやすくなっています。

a=1,
b=2,

に:

'a': 1,
'b': 2,

また、後で名前付きのタプルまたはクラスのインスタンスに変換したいと思う状況でも役立ちます。

実装自体では、最適化への執着があり、特に保守性に大きなメリットが見られない場合は、常に中括弧を使用します。

テストと実装では、その後に追加されたキー、または将来的に次のいずれかになる可能性がある場合は、dict()を使用しません。

  • 常に文字列ではありません
  • 数字、ASCII文字、アンダースコアだけでなく
  • 整数で開始します(dict(1foo=2)SyntaxErrorが発生します)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.