В чем разница между 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']])

и целый ряд других способов с

8 ответов


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


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

>>> from timeit import timeit
>>> timeit("a = {'a': 1, 'b': 2}")
0.424...
>>> timeit("a = dict(a = 1, b = 2)")
0.889...

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

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

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

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

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

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

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

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

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


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


обновление: спасибо за ответы. Удалены спекуляции о copy-on-write.

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

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

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


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

dict( generator which yields (key,value) pairs )
dict( list of (key,value) pairs )

забавный использование:

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

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

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

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