dict()和{}之间有什么区别?

时间:2023-01-24 00:02:39

So let's say I wanna make a dictionary. We'll call it d. But there are multiple ways to initialize a dictionary in Python! For example, I could do this:

假设我想编一个字典。我们称它为d。但是在Python中有多种方法来初始化字典!例如,我可以这样做:

d = {'hash': 'bang', 'slash': 'dot'}

Or I could do this:

或者我可以这样做:

d = dict(hash='bang', slash='dot')

Or this, curiously:

或者,奇怪的是:

d = dict({'hash': 'bang', 'slash': 'dot'})

Or this:

或:

d = dict([['hash', 'bang'], ['slash', 'dot']])

And a whole other multitude of ways with the dict() function. So obviously one of the things dict() provides is flexibility in syntax and initialization. But that's not what I'm asking about.

和具有dict()功能的其他许多方法。显然,dict()所提供的内容之一是语法和初始化方面的灵活性。但这不是我要问的。

Say I were to make d just an empty dictionary. What goes on behind the scenes of the Python interpreter when I do d = {} versus d = dict()? Is it simply two ways to do the same thing? Does using {} have the additional call of dict()? Does one have (even negligible) more overhead than the other? While the question is really completely unimportant, it's a curiosity I would love to have answered.

假设我要做一本空字典。当我执行d ={}与d = dict()时,在Python解释器的幕后会发生什么?这仅仅是做同一件事的两种方式吗?使用{}是否有附加的dict()调用?一个(甚至可以忽略)比另一个有更多的开销吗?虽然这个问题完全不重要,但我很想回答这个问题。

8 个解决方案

#1


61  

>>> 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() is apparently some C built-in. A really smart or dedicated person (not me) could look at the interpreter source and tell you more. I just wanted to show off dis.dis. :)

dict()显然是某种内置的C。一个真正聪明或有奉献精神的人(不是我)可以查看解释器源代码并告诉你更多。我只是想炫耀一下。:)

#2


31  

As far as performance goes:

就性能而言:

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

#3


25  

@Jacob: There is a difference in how the objects are allocated, but they are not copy-on-write. Python allocates a fixed-size "free list" where it can quickly allocate dictionary objects (until it fills). Dictionaries allocated via the {} syntax (or a C call to PyDict_New) can come from this free list. When the dictionary is no longer referenced it gets returned to the free list and that memory block can be reused (though the fields are reset first).

@Jacob:分配对象的方式不同,但它们不是写后复制。Python分配一个固定大小的“空闲列表”,在其中可以快速分配字典对象(直到它填满)。通过{}语法分配的字典(或对PyDict_New的C调用)可以来自这个*列表。当字典不再被引用时,它将被返回到空闲列表,并且该内存块可以被重用(尽管字段首先被重置)。

This first dictionary gets immediately returned to the free list, and the next will reuse its memory space:

第一个字典立即返回到空闲列表,下一个字典将重用它的内存空间:

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

If you keep a reference, the next dictionary will come from the next free slot:

如果你有参考资料,下一本字典将来自下一个免费的插槽:

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

But we can delete the reference to that dictionary and free its slot again:

但我们可以删除对该词典的引用,并再次释放它的插槽:

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

Since the {} syntax is handled in byte-code it can use this optimization mentioned above. On the other hand dict() is handled like a regular class constructor and Python uses the generic memory allocator, which does not follow an easily predictable pattern like the free list above.

由于{}语法是在字节码中处理的,所以可以使用上面提到的这种优化。另一方面,像常规类构造函数一样处理dict(),而Python使用通用内存分配器,它不遵循像上面的*列表那样容易预测的模式。

Also, looking at compile.c from Python 2.6, with the {} syntax it seems to pre-size the hashtable based on the number of items it's storing which is known at parse time.

同时,在编译。c来自Python 2.6,使用{}语法,它似乎根据存储在解析时已知的项的数量对哈希表进行了预处理。

#4


8  

Basically, {} is syntax and is handled on a language and bytecode level. dict() is just another builtin with a more flexible initialization syntax. Note that dict() was only added in the middle of 2.x series.

基本上,{}是语法,并在语言和字节码级别上处理。dict()只是另一个具有更灵活的初始化语法的内置函数。注意,dict()只在2的中间添加。x系列。

#5


5  

Update: thanks for the responses. Removed speculation about copy-on-write.

更新:感谢您的回复。即写即拷的猜测。

One other difference between {} and dict is that dict always allocates a new dictionary (even if the contents are static) whereas {} doesn't always do so (see mgood's answer for when and why):

{}和dict之间的另一个区别是,dict总是分配一个新的字典(即使内容是静态的),而{}并不总是这样做(参见mgood关于何时和为什么):

def dict1():
    return {'a':'b'}

def dict2():
    return dict(a='b')

print id(dict1()), id(dict1())
print id(dict2()), id(dict2())

produces:

生产:

$ ./mumble.py
11642752 11642752
11867168 11867456

I'm not suggesting you try to take advantage of this or not, it depends on the particular situation, just pointing it out. (It's also probably evident from the disassembly if you understand the opcodes).

我并不是建议你去利用它,这取决于具体情况,只指出它。(如果你理解操作码,从拆解中也可以看出这一点)。

#6


3  

dict() is used when you want to create a dictionary from an iterable, like :

当您想从可迭代的字典中创建字典时,使用dict(),比如:

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

#7


1  

Funny usage:

有趣的用法:

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)

output:

输出:

I want to be printed
a

#8


-1  

In order to create an empty set we should use the keyword set before it i.e set() this creates an empty set where as in dicts only the flower brackets can create an empty dict

为了创建空集,我们应该在它之前使用关键字集。e set()这将创建一个空集,其中只有花括号可以创建一个空的dict类型

Lets go with an example

让我们举个例子

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

#1


61  

>>> 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() is apparently some C built-in. A really smart or dedicated person (not me) could look at the interpreter source and tell you more. I just wanted to show off dis.dis. :)

dict()显然是某种内置的C。一个真正聪明或有奉献精神的人(不是我)可以查看解释器源代码并告诉你更多。我只是想炫耀一下。:)

#2


31  

As far as performance goes:

就性能而言:

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

#3


25  

@Jacob: There is a difference in how the objects are allocated, but they are not copy-on-write. Python allocates a fixed-size "free list" where it can quickly allocate dictionary objects (until it fills). Dictionaries allocated via the {} syntax (or a C call to PyDict_New) can come from this free list. When the dictionary is no longer referenced it gets returned to the free list and that memory block can be reused (though the fields are reset first).

@Jacob:分配对象的方式不同,但它们不是写后复制。Python分配一个固定大小的“空闲列表”,在其中可以快速分配字典对象(直到它填满)。通过{}语法分配的字典(或对PyDict_New的C调用)可以来自这个*列表。当字典不再被引用时,它将被返回到空闲列表,并且该内存块可以被重用(尽管字段首先被重置)。

This first dictionary gets immediately returned to the free list, and the next will reuse its memory space:

第一个字典立即返回到空闲列表,下一个字典将重用它的内存空间:

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

If you keep a reference, the next dictionary will come from the next free slot:

如果你有参考资料,下一本字典将来自下一个免费的插槽:

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

But we can delete the reference to that dictionary and free its slot again:

但我们可以删除对该词典的引用,并再次释放它的插槽:

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

Since the {} syntax is handled in byte-code it can use this optimization mentioned above. On the other hand dict() is handled like a regular class constructor and Python uses the generic memory allocator, which does not follow an easily predictable pattern like the free list above.

由于{}语法是在字节码中处理的,所以可以使用上面提到的这种优化。另一方面,像常规类构造函数一样处理dict(),而Python使用通用内存分配器,它不遵循像上面的*列表那样容易预测的模式。

Also, looking at compile.c from Python 2.6, with the {} syntax it seems to pre-size the hashtable based on the number of items it's storing which is known at parse time.

同时,在编译。c来自Python 2.6,使用{}语法,它似乎根据存储在解析时已知的项的数量对哈希表进行了预处理。

#4


8  

Basically, {} is syntax and is handled on a language and bytecode level. dict() is just another builtin with a more flexible initialization syntax. Note that dict() was only added in the middle of 2.x series.

基本上,{}是语法,并在语言和字节码级别上处理。dict()只是另一个具有更灵活的初始化语法的内置函数。注意,dict()只在2的中间添加。x系列。

#5


5  

Update: thanks for the responses. Removed speculation about copy-on-write.

更新:感谢您的回复。即写即拷的猜测。

One other difference between {} and dict is that dict always allocates a new dictionary (even if the contents are static) whereas {} doesn't always do so (see mgood's answer for when and why):

{}和dict之间的另一个区别是,dict总是分配一个新的字典(即使内容是静态的),而{}并不总是这样做(参见mgood关于何时和为什么):

def dict1():
    return {'a':'b'}

def dict2():
    return dict(a='b')

print id(dict1()), id(dict1())
print id(dict2()), id(dict2())

produces:

生产:

$ ./mumble.py
11642752 11642752
11867168 11867456

I'm not suggesting you try to take advantage of this or not, it depends on the particular situation, just pointing it out. (It's also probably evident from the disassembly if you understand the opcodes).

我并不是建议你去利用它,这取决于具体情况,只指出它。(如果你理解操作码,从拆解中也可以看出这一点)。

#6


3  

dict() is used when you want to create a dictionary from an iterable, like :

当您想从可迭代的字典中创建字典时,使用dict(),比如:

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

#7


1  

Funny usage:

有趣的用法:

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)

output:

输出:

I want to be printed
a

#8


-1  

In order to create an empty set we should use the keyword set before it i.e set() this creates an empty set where as in dicts only the flower brackets can create an empty dict

为了创建空集,我们应该在它之前使用关键字集。e set()这将创建一个空集,其中只有花括号可以创建一个空的dict类型

Lets go with an example

让我们举个例子

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