2010-02-24 19 views
20

che devo risolvere questo esercizio:Python: Estendere la 'dict' classe

dizionari di Python non lo fanno mantenere l'ordine dei dati inseriti, né memorizzare i dati ordinati dal tasto. Scrivi un'estensione per la classe dict le cui istanze manterranno i dati ordinati in base al loro valore chiave. Si noti che l'ordine deve essere mantenuto anche quando vengono aggiunti nuovi elementi.

Come prolungare dict? Devo avere accesso al codice sorgente per il tipo dict?

+2

hmmm ... compiti a casa? – jldupont

risposta

27

È possibile sia sottoclasse dict o UserDict, poiché van già parlato di UserDict, consente di guardare dict.

Digitare help(dict) in un interprete e si vede una grande lista di metodi. Sarà necessario sovrascrivere tutti i metodi che modificano il dict e i metodi che eseguono l'iterazione rispetto al dettato.

I metodi che modificano il dict includono __delitem__, __setitem__, clear ecc

I metodi che iterarlo dict includere __iter__, keys, values, items ecc

Questo dovrebbe iniziare

>>> class odict(dict): 
...  def __init__(self, *args, **kw): 
...   super(odict,self).__init__(*args, **kw) 
...   self.itemlist = super(odict,self).keys() 
...  def __setitem__(self, key, value): 
...   # TODO: what should happen to the order if 
...   #  the key is already in the dict  
...   self.itemlist.append(key) 
...   super(odict,self).__setitem__(key, value) 
...  def __iter__(self): 
...   return iter(self.itemlist) 
...  def keys(self): 
...   return self.itemlist 
...  def values(self): 
...   return [self[key] for key in self] 
...  def itervalues(self): 
...   return (self[key] for key in self) 
... 
>>> od = odict(a=1,b=2) 
>>> print od 
{'a': 1, 'b': 2} 
>>> od['d']=4 
>>> od['c']=3 
>>> print od # look at the `__str__` and `__repr__` methods 
{'a': 1, 'c': 3, 'b': 2, 'd': 4} 
>>> print od.keys() 
['a', 'b', 'd', 'c'] 
>>> print od.values() 
[1, 2, 4, 3] 
+0

c'è qualche possibilità di un esempio funzionante con python 3? Ho iniziato a cambiare 'self.itemlist.append (chiave)' con 'set (self.itemlist) .add (chiave)' per farlo funzionare, ma l'ordine non è più conservato – z3d0

+0

@ z3d0r, In Python3, '.keys () 'non restituisce più una lista, quindi dovresti usare' self.itemlist = list (super (odict, self) .keys()) 'nel metodo' __init__'. –

+0

grazie, ho anche notato che i metodi 'values ​​()' e 'itervalues ​​()' non esistono più e che 'keys()' è un set e non un elenco, quindi sarebbe 'def keys (self): set di ritorno (self.itemlist) 'essere corretto? Ci stiamo ancora lavorando perché l'ordine non è ancora conservato – z3d0

9

L'implementazione di dict non ti aiuterà con il compito. Quello che vuoi è una classe che abbia la stessa interfaccia di dict, ma una diversa implementazione. That will require to implement methods like __getitem__, __setitem__, etc. Se Google per "ordereddict", troverete molti esempi.

+2

Leggi le informazioni collections.ABC sull'estensione del 'Mapping' per implementare un dizionario ordinato.http://docs.python.org/library/collections.html#abcs-abstract-base-classes. –

5

Se si utilizza python 2.7+, vedere collections.OrderedDict.
Altrimenti, backport (copiare la fonte) o vedere Recipe 576693: Ordered Dictionary for Py2.4 (Python).

Ma se si ha realmente bisogno di estendere il dict, quindi iniziare con UserDict, fonte per la quale si può trovare in /lib/UserDict.py della vostra distribuzione Python.

+0

@ user280560: Se lo fai, assicurati di dire al tuo istruttore da dove hai preso il codice, dal momento che non lo hai scritto, ma lo hai ridimensionato. –

+0

@ S.Lott: Immagino che non gli sia consentito copiare e incollare e che stiano usando 2.5/2.6. – voyager

+2

Non penso che il compito fosse implementare 'OrderedDict', dato che conserva l'ordine _insertion_ piuttosto che mantenere l'ordine delle chiavi ordinate. –

5

Buone notizie: il problema non è affatto difficile.

Per curiosare in giro e vedere le viscere di un class è possibile utilizzare

>>> dir(dict) 
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values'] 

e help(dict), che ha una documentazione interattiva molto completo, ma ovviamente è anche avere accesso alla ancora più completa online documentation .

Una volta compreso ciò che fa dict dietro le quinte, è necessario conoscere inheritance in Python.

Se rimani bloccato visita this site per ottenere alcune idee, ma non copiare/incollare, il vostro insegnante non lo vedrà gentilmente.