Каков предпочтительный синтаксис для инициализации dict: фигурные скобки литералов {} или функция dict ()?

212

Я прилагаю некоторые усилия для изучения Python и уделяю пристальное внимание общим стандартам кодирования. Это может показаться бессмысленным, но я пытаюсь сосредоточиться на передовых практиках, так как я учусь, поэтому мне не нужно избавляться от «плохих» привычек.

Я вижу два распространенных метода инициализации слова:

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

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

Что считается "более питоническим"? Что вы используете? Зачем?

daotoad
источник
5
Какой учебник вы используете? Где вы видели примеры, которые приводят к путанице?
С.Лотт
2
Ну, я использовал учебник по Python, Dive into Python, а затем множество блогов, SO сообщений и других ресурсов Googled. Официальные документы используются {}довольно равномерно, но я вижу много явного dict()подхода в другом месте. Я мог видеть выгоду от явного синтаксиса, но отсутствие подхода в официальных документах вызывало у меня подозрения. После публикации я просмотрел документы библиотеки dictи обнаружил предупреждение о том, что ключи должны быть действительными идентификаторами, когда dictдля инициализации dict используется явное .
Даотоад
2
Как "dict ()" более явно, чем "{}"? Я не понимаю вашу путаницу. Оба кажутся мне явными. Можете ли вы предоставить цитату или ссылку, которая заставляет вас сказать, что «dict» является «явным», а «{}» не является явным? Как вы думаете, откуда возникло это различие?
С.Лотт
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'}. Второй вариант работает только для (некоторых) строковых ключей. Использование различных типов синтаксиса в зависимости от типа ключей было бы ненужным несоответствием.
  • Это быстрее:

    $ 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
  • Если бы специальный синтаксис для литералов словаря не предназначался для использования, он, вероятно, не существовал бы.
Stephan
источник
3

Я думаю, что первый вариант лучше, потому что вы собираетесь получить доступ к значениям как ['a'] или ['other']. Ключи в вашем словаре являются строками, и нет никаких оснований делать вид, что это не так. Для меня синтаксис ключевого слова на первый взгляд выглядит умным, а на второй взгляд - неясным. Это имеет смысл только для меня, если вы работаете __dict__, и ключевые слова станут атрибутами позже, что-то вроде этого.

dividebyzero
источник
3

К вашему сведению, если вам нужно добавить атрибуты в ваш словарь (вещи, которые прикреплены к словарю, но не являются одним из ключей), тогда вам понадобится вторая форма. В этом случае вы можете инициализировать свой словарь ключами, содержащими произвольные символы, по одному, например, так:

    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) для x в диапазоне (0,7)]))

Дэцин
источник
2
Существует функция перечисления, которая может сделать это лучше. В этом отношении есть тип Enum, который может делать то, что вы делаете здесь лучше. Кроме того, это не совсем ответ на вопрос вообще.
dusktreader
2

Я почти всегда использую фигурные скобки; однако, в некоторых случаях, когда я пишу тесты, я делаю упаковку / распаковку ключевых слов, и в этих случаях dict () гораздо более удобен в обслуживании, поскольку мне не нужно менять:

a=1,
b=2,

чтобы:

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

Это также помогает в некоторых обстоятельствах, когда я думаю, что я мог бы захотеть превратить его в именованный кортеж или экземпляр класса позже.

В самой реализации, из-за моей одержимости оптимизацией, и когда я не вижу особого преимущества в обслуживании, я всегда предпочитаю фигурные скобки.

В тестах и ​​реализации я бы никогда не использовал dict (), если есть вероятность, что ключи, добавленные тогда или в будущем, будут либо:

  • Не всегда быть строкой
  • Не только содержат цифры, буквы ASCII и подчеркивания
  • Начать с целого числа ( dict(1foo=2)вызывает ошибку SyntaxError)
user989266
источник