Який переважний синтаксис для ініціалізації дікта: фігурні дужки-дужки {} або функція dict ()?


212

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

Я бачу два поширених способу ініціалізації дикта:

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

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

Що вважається "більш пітонічним"? Яким ти користуєшся? Чому?


5
Який підручник ви використовуєте? Де ви бачили приклади, які призводять до плутанини?
С.Лотт

2
Ну, я використовував підручник з Python, занурюючись у Python, а потім різноманітні блоги, публікації SO та інші ресурси Google. Офіційні документи використовують {}досить рівномірно, але я бачу багато явного dict()підходу в інших місцях. Я бачив користь явного синтаксису, але відсутність підходу в офіційних документах зробила мене підозрілою. Опублікувавши це, я переглянув документи бібліотеки dictі виявив обережність, що dictдля ініціалізації диктанту ключі повинні бути дійсними ідентифікаторами .
даотоад

2
Як "dict ()" явніше, ніж "{}"? Я не розумію вашої плутанини. Обидва мені здаються явними. Чи можете ви надати цитату чи посилання, що змушує вас сказати, що "dict" є "явним", а "{}" не є явним? Як ви думаєте, звідки виникла ця відмінність?
С.Лотт

21
Відмінність - правопис. dict()написано dict- використовує ім'я типу. Дужки ( {}) покладаються на розділові знаки, щоб визначити тип.
даотоад

Відповіді:


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
  • Якби спеціальний синтаксис для літеральних словників не використовувався, він, ймовірно, не існував.

3

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


3

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

    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,

Це також допомагає в деяких обставинах, коли, я думаю, я можу згодом перетворити його на ім'я nametuple або class.

У самому впровадженні, через мою одержимість оптимізацією, і коли я не бачу особливо великої користі у обслуговуванні, я завжди віддаю перевагу фігурним брекетам.

У тестах та впровадженні я ніколи не використовував dict (), якщо є ймовірність, що ключі, додані тоді, або в майбутньому:

  • Не завжди бути рядком
  • Не тільки містять цифри, букви ASCII та підкреслення
  • Почніть з цілого числа ( dict(1foo=2)підвищує SyntaxError)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.