В чем разница между dict () и {}? - PullRequest
59 голосов
/ 20 марта 2009

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

Ответы [ 8 ]

71 голосов
/ 20 марта 2009
>>> 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 (), по-видимому, является встроенным в Си. Действительно умный или преданный человек (не я) мог бы посмотреть на источник переводчика и рассказать вам больше. Я просто хотел похвастаться dis.dis. :)

37 голосов
/ 20 марта 2009

Насколько производительность идет:

>>> from timeit import timeit
>>> timeit("a = {'a': 1, 'b': 2}")
0.424...
>>> timeit("a = dict(a = 1, b = 2)")
0.889...
26 голосов
/ 25 марта 2009

@ Джейкоб: Есть разница в том, как объекты распределяются, но они не копируются при записи. Python выделяет «свободный список» фиксированного размера, где он может быстро размещать объекты словаря (до тех пор, пока он не заполнится). Словари, выделенные с помощью синтаксиса {} (или вызова C на PyDict_New), могут быть получены из этого свободного списка. Когда на словарь больше не ссылаются, он возвращается в свободный список, и этот блок памяти можно использовать повторно (хотя поля сбрасываются первыми).

Этот первый словарь немедленно возвращается в свободный список, а следующий снова использует пространство памяти:

>>> id({})
340160
>>> id({1: 2})
340160

Если вы сохраните ссылку, следующий словарь появится в следующем свободном слоте:

>>> x = {}
>>> id(x)
340160
>>> id({})
340016

Но мы можем удалить ссылку на этот словарь и снова освободить его слот:

>>> del x
>>> id({})
340160

Поскольку синтаксис {} обрабатывается в байт-коде, он может использовать эту оптимизацию, упомянутую выше. С другой стороны, dict() обрабатывается как обычный конструктор классов, а Python использует универсальный распределитель памяти, который не следует легко предсказуемому шаблону, как свободный список выше.

Также, глядя на compile.c из Python 2.6, с синтаксисом {} кажется, что он предварительно изменяет размер хеш-таблицы на основе количества элементов, которые он хранит, что известно во время разбора.

8 голосов
/ 20 марта 2009

По сути, {} является синтаксисом и обрабатывается на уровне языка и байт-кода. dict () - это просто еще одно встроенное средство с более гибким синтаксисом инициализации. Обратите внимание, что dict () был добавлен только в середине серии 2.x.

6 голосов
/ 20 марта 2009

Обновление : спасибо за ответы. Удалено предположение о копировании при записи.

Еще одно различие между {} и dict заключается в том, что dict всегда выделяет новый словарь (даже если его содержимое статично), тогда как {} не всегда делает это (см. ответ мгуда когда и почему):

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

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

3 голосов
/ 30 апреля 2011

dict () используется, когда вы хотите создать словарь из итерируемого, например:

dict( generator which yields (key,value) pairs )
dict( list of (key,value) pairs )
1 голос
/ 06 февраля 2018

Смешное использование:

def func(**kwargs):
      for e in kwargs:
        print(e)
    a = 'I want to be printed'
    kwargs={a:True}
    func(**kwargs)
    a = 'I dont want to be printed'
    kwargs=dict(a=True)
    func(**kwargs)

выход:

I want to be printed
a
0 голосов
/ 31 мая 2016

Чтобы создать пустой набор, мы должны использовать перед ним ключевое слово. то есть set() это создает пустой набор, где, как и в случае с диктовками, только цветочные скобки могут создавать пустые слова

Давайте рассмотрим пример

print isinstance({},dict) 
True 
print isinstance({},set) 
False 
print isinstance(set(),set) 
True
...