Какая разница между dict() и {}?
Итак, скажем, я хочу сделать словарь. Мы назовем его d
. Но есть несколько способов инициализации словаря в Python! Например, я мог бы сделать это:
d = {'hash': 'bang', 'slash': 'dot'}
Или я мог бы сделать это:
d = dict(hash='bang', slash='dot')
Или это, с любопытством:
d = dict({'hash': 'bang', 'slash': 'dot'})
Или это:
d = dict([['hash', 'bang'], ['slash', 'dot']])
И целый ряд способов с помощью функции dict()
. Таким образом, очевидно, что одна из вещей dict()
обеспечивает гибкость в синтаксисе и инициализации. Но это не то, о чем я прошу.
Скажем, я должен был сделать d
просто пустой словарь. Что происходит за кулисами интерпретатора Python, когда я делаю d = {}
versus d = dict()
? Это просто два способа сделать то же самое? Использует ли {}
вызов дополнительных dict()
? Имеет ли (даже незначительное) больше накладных расходов, чем другие? Хотя вопрос действительно совершенно неважен, это любопытство, на которое я бы хотел ответить.
Ответы
Ответ 1
>>> def f():
... return {'a' : 1, 'b' : 2}
...
>>> def g():
... return dict(a=1, b=2)
...
>>> g()
{'a': 1, 'b': 2}
>>> f()
{'a': 1, 'b': 2}
>>> import dis
>>> dis.dis(f)
2 0 BUILD_MAP 0
3 DUP_TOP
4 LOAD_CONST 1 ('a')
7 LOAD_CONST 2 (1)
10 ROT_THREE
11 STORE_SUBSCR
12 DUP_TOP
13 LOAD_CONST 3 ('b')
16 LOAD_CONST 4 (2)
19 ROT_THREE
20 STORE_SUBSCR
21 RETURN_VALUE
>>> dis.dis(g)
2 0 LOAD_GLOBAL 0 (dict)
3 LOAD_CONST 1 ('a')
6 LOAD_CONST 2 (1)
9 LOAD_CONST 3 ('b')
12 LOAD_CONST 4 (2)
15 CALL_FUNCTION 512
18 RETURN_VALUE
dict(), по-видимому, встроен в C. Действительно умный или преданный человек (а не я) мог посмотреть на источник переводчика и рассказать вам больше. Я просто хотел показать dis.dis.:)
Ответ 2
Что касается производительности:
>>> from timeit import timeit
>>> timeit("a = {'a': 1, 'b': 2}")
0.424...
>>> timeit("a = dict(a = 1, b = 2)")
0.889...
Ответ 3
@Jacob: существует разница в распределении объектов, но они не копируются на запись. Python выделяет "свободный список" фиксированного размера, где он может быстро выделять объекты словаря (пока он не заполнится). Слои, выделенные с помощью синтаксиса {}
(или вызова C на PyDict_New
), могут поступать из этого бесплатного списка. Когда словарь больше не ссылается, он возвращается в свободный список и этот блок памяти может быть повторно использован (хотя сначала поля reset).
Этот первый словарь сразу же возвращается в свободный список, а следующий будет повторно использовать его пространство памяти:
>>> id({})
340160
>>> id({1: 2})
340160
Если вы сохраните ссылку, следующий словарь появится из следующего свободного слота:
>>> x = {}
>>> id(x)
340160
>>> id({})
340016
Но мы можем удалить ссылку на этот словарь и снова освободить его слот:
>>> del x
>>> id({})
340160
Поскольку синтаксис {}
обрабатывается в байтовом коде, он может использовать упомянутую выше оптимизацию. С другой стороны, dict()
обрабатывается как обычный конструктор классов, а Python использует общий распределитель памяти, который не следует легко прогнозируемому шаблону, например, свободному списку.
Кроме того, глядя на compile.c из Python 2.6, с синтаксисом {}
, кажется, предварительно размер хэш-таблицы, основанный на количестве элементов, которые он хранит, который известен во время разбора.
Ответ 4
В принципе, {} является синтаксисом и обрабатывается на уровне языка и байт-кода. dict() - это еще один вариант с более гибким синтаксисом инициализации. Обратите внимание, что dict() был добавлен только в середине серии 2.x.
Ответ 5
Обновление: спасибо за ответы. Устранены предположения о копировании на запись.
Еще одно отличие между {}
и dict
заключается в том, что dict
всегда выделяет новый словарь (даже если содержимое является статическим), тогда как {}
не всегда делает это (см. mgood answer, когда и почему):
def dict1():
return {'a':'b'}
def dict2():
return dict(a='b')
print id(dict1()), id(dict1())
print id(dict2()), id(dict2())
дает:
$ ./mumble.py
11642752 11642752
11867168 11867456
Я не предлагаю вам попытаться воспользоваться этим или нет, это зависит от конкретной ситуации, просто указывая на это. (Это также очевидно из разборки, если вы понимаете коды операций).
Ответ 6
dict() используется, когда вы хотите создать словарь из итерации, например:
dict( generator which yields (key,value) pairs )
dict( list of (key,value) pairs )
Ответ 7
Чтобы создать пустой набор, мы должны использовать перед ним набор ключевых слов
i.e set()
создает пустой набор, где, как и в dict, только цветочные скобки могут создать пустой dict
Давайте рассмотрим пример
print isinstance({},dict)
True
print isinstance({},set)
False
print isinstance(set(),set)
True