Domanda

Quindi diciamo che voglio creare un dizionario. Lo chiameremo d. Ma ci sono molti modi per inizializzare un dizionario in Python! Ad esempio, potrei farlo:

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

O potrei farlo:

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

O questo, curiosamente:

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

O questo:

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

E tutta un'altra moltitudine di modi con la funzione dict(). Quindi ovviamente una delle cose che d = {} offre è la flessibilità nella sintassi e nell'inizializzazione. Ma non è quello che sto chiedendo.

Supponi che dovrei creare d = dict() solo un dizionario vuoto. Cosa succede dietro le quinte dell'interprete Python quando faccio {} contro <=>? Sono semplicemente due modi per fare la stessa cosa? L'uso di <=> ha la chiamata aggiuntiva di <=>? Uno ha (anche se trascurabile) più spese generali dell'altro? Mentre la domanda è davvero completamente irrilevante, è una curiosità a cui mi piacerebbe aver risposto.

È stato utile?

Soluzione

>>> 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 () è apparentemente un C incorporato. Una persona davvero intelligente o dedicata (non io) potrebbe guardare la fonte dell'interprete e dirti di più. Volevo solo mostrare dis.dis. :)

Altri suggerimenti

Per quanto riguarda le prestazioni:

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

@Jacob: c'è una differenza nel modo in cui gli oggetti sono allocati, ma non sono copy-on-write. Python alloca un & Quot di dimensioni fisse; lista libera & Quot; dove può allocare rapidamente gli oggetti del dizionario (fino a quando non si riempie). I dizionari assegnati tramite la sintassi {} (o una chiamata C a PyDict_New) possono provenire da questo elenco gratuito. Quando il dizionario non fa più riferimento, viene restituito all'elenco libero e quel blocco di memoria può essere riutilizzato (anche se i campi vengono ripristinati per primi).

Questo primo dizionario viene immediatamente riportato all'elenco gratuito e il successivo riutilizzerà il suo spazio di memoria:

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

Se mantieni un riferimento, il prossimo dizionario verrà dal prossimo spazio libero:

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

Ma possiamo eliminare il riferimento a quel dizionario e liberare di nuovo il suo slot:

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

Poiché la sintassi dict() è gestita in codice byte, può utilizzare questa ottimizzazione sopra menzionata. D'altra parte, <=> viene gestito come un normale costruttore di classi e Python utilizza l'allocatore di memoria generico, che non segue uno schema facilmente prevedibile come l'elenco libero sopra.

Inoltre, guardando compile.c da Python 2.6, con la sintassi <=> sembra pre-dimensionare la tabella hash in base al numero di elementi che sta memorizzando che è noto al momento dell'analisi.

Fondamentalmente, {} è sintassi ed è gestito a livello di lingua e bytecode. dict () è solo un altro builtin con una sintassi di inizializzazione più flessibile. Nota che dict () è stato aggiunto solo nel mezzo della serie 2.x.

Aggiorna : grazie per le risposte. Rimossa la speculazione su copia su scrittura.

Un'altra differenza tra {} e dict è che <=> alloca sempre un nuovo dizionario (anche se i contenuti sono statici) mentre <=> non sempre ( vedi la risposta di mgood per quando e perché):

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

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

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

produce:

$ ./mumble.py
11642752 11642752
11867168 11867456

Non sto suggerendo di provare a trarre vantaggio da questo o no, dipende dalla situazione particolare, basta sottolinearlo. (Probabilmente è anche evidente dal smontaggio se si capisce il codici operativi).

dict () viene utilizzato quando si desidera creare un dizionario da un iterabile, come:

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

Uso divertente:

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)

uscita:

I want to be printed
a

Per creare un set vuoto dovremmo usare il set di parole chiave prima di esso vale a dire set() questo crea un set vuoto dove come in dicts solo le parentesi di fiori possono creare un dict vuoto

Andiamo con un esempio

print isinstance({},dict) 
True 
print isinstance({},set) 
False 
print isinstance(set(),set) 
True
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top