Подтвердить что ты не робот

Какая разница между 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()? Имеет ли (даже незначительное) больше накладных расходов, чем другие? Хотя вопрос действительно совершенно неважен, это любопытство, на которое я бы хотел ответить.

4b9b3361

Ответ 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