Есть ли разница между использованием dict-литерала и dict-конструктора? - PullRequest
180 голосов
/ 07 июля 2011

Используя PyCharm, я заметил, что он предлагает преобразовать dict литерал :

d = {
    'one': '1',
    'two': '2',
}

в конструктор dict :

d = dict(one='1', two='2')

Отличаются ли эти разные подходы каким-либо существенным образом?

(При написании этого вопроса я заметил, что с помощьюdict() кажется невозможным указать цифровую клавишу. d = {1: 'one', 2: 'two'} возможно, но, очевидно, dict(1='one' ...) - нет. Что-нибудь еще?)

Ответы [ 10 ]

107 голосов
/ 07 июля 2011

Я думаю, что вы указали на наиболее очевидную разницу. Кроме того,

первый не должен искать dict, что должно сделать его чуть-чуть быстрее

второй ищет dict в locals(), а затем globals() и находит встроенную функцию, так что вы можете переключить поведение, определив, например, локальный номер dict, хотя я нигде не могу придумать было бы хорошей идеей, кроме, может быть, при отладке

50 голосов
/ 07 июля 2011

Literal намного быстрее, поскольку использует оптимизированные коды операций BUILD_MAP и STORE_MAP, а не универсальный CALL_FUNCTION:

> 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
38 голосов
/ 07 июля 2011

Они выглядят почти одинаково на 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
13 голосов
/ 07 июля 2011

Эти два подхода создают идентичные словари, за исключением, как вы заметили, где лексические правила Python мешают.

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

a = "hello"
d = {
    a: 'hi'
    }

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

Я понятия не имею, почему PyCharm предлагает преобразовать одну форму в другую.

7 голосов
/ 02 февраля 2016

Одна большая разница с python 3.4 + pycharm заключается в том, что конструктор dict () выдает сообщение «синтаксическая ошибка», если количество ключей превышает 256.

Я предпочитаю использовать литерал dict сейчас.

6 голосов
/ 07 июля 2011

Из Python 2.7 учебник:

Пара скобок создает пустой толковый словарь: {}. Размещение разделенный запятыми список ключей: значение пары в фигурных скобках добавляет начальные ключ: значение пары в словаре; это также, как словари написано на выходе.

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 () создают словарь, но предоставляют немного разные способы инициализации данных словаря.

2 голосов
/ 22 сентября 2017

Не существует литерала dict для создания классов, унаследованных от dict, пользовательских классов dict с дополнительными методами. В таком случае следует использовать пользовательский конструктор класса dict, например:

class NestedDict(dict):

    # ... skipped

state_type_map = NestedDict(**{
    'owns': 'Another',
    'uses': 'Another',
})
2 голосов
/ 04 ноября 2015

Я нахожу, что dict литерал d = {'one': '1'} гораздо более читабелен, ваши определяющие данные, а не присваивают значения вещей и отправляют их конструктору dict().

С другой стороны, я видел людейопечатайте dict литерал как d = {'one', '1'}, который в современном Python 2.7+ создаст набор.

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

0 голосов
/ 26 июня 2017

Также учтите тот факт, что токены, которые соответствуют операторам, не могут использоваться в синтаксисе конструктора, то есть в дашеризированных ключах.

>>> dict(foo-bar=1)
File "<stdin>", line 1
SyntaxError: keyword can't be an expression

>>> {'foo-bar': 1}
{'foo-bar': 1}
0 голосов
/ 21 июля 2016

Литерал dict () удобен, когда вы копируете вставленные значения из чего-то другого (без python) Например, список переменных среды. если у вас был файл bash, скажите

FOO='bar'
CABBAGE='good'

Вы можете легко вставить затем в dict() литерал и добавить комментарии. Это также облегчает обратное, копирование во что-то другое. Принимая во внимание, что синтаксис {'FOO': 'bar'} довольно уникален для python и json. Так что если вы часто используете json, вы можете использовать {} литералы с двойными кавычками.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...