2013-01-21 14 views
8

voglio fare qualcosa di simile:Alias ​​per il funzionamento dizionario in Python

f[frozenset((1,3,4))] = 5 
f[frozenset((1,))] = 3 

ma è solo doloroso per digitare questi tutto il tempo, c'è comunque di avere alias per questo? So che in C++ è possibile avere una funzione di supporto che restituiscono un riferimento in modo da poter digitare semplicemente:

F(1,3,4) = 5 
F(1) = 3 

con F come una funzione di supporto. Grazie mille!

risposta

13

ritengo che questo può davvero essere ottenuto solo tramite una sottoclasse:

class FrozenSetDict(dict): 
    def __setitem__(self,idx,value): 
     try: 
      dict.__setitem__(self,frozenset(idx),value) 
     except TypeError: 
      dict.__setitem__(self,frozenset((idx,)),value) 

d = FrozenSetDict() 
d[1,2,3] = 4 
d[1] = 5 
print d 

rendimenti:

{frozenset([1, 2, 3]): 4, frozenset([1]): 5} 

Questo introduce un'asimmetria tra __getitem__ e __setitem__ che potrebbe essere facilmente fissato ridefinendo __getitem__ allo stesso modo.

Questo potrebbe sembrare un po 'disordinato - Infatti lo è. Perché richiedere una sottoclasse? Questo rende solo più difficile mettere gli oggetti non-frozenset nel tuo dizionario come chiavi. Si potrebbe facilmente utilizzare questa ricetta anche per creare un oggetto proxy che fare questo con il vostro dict:

#I don't like the name of this class -- I'm open to suggestions :) 
class FrozenSetProxy(object): 
    def __init__(self,obj): 
     self.obj = obj 

    def __setitem__(self,idx,value): 
     try: 
      self.obj[frozenset(idx)] = value 
     except TypeError: 
      self.obj[frozenset((idx,))] = value 

    def __getitem__(self,idx): 
     try: 
      return self.obj[frozenset(idx)] 
     except TypeError: 
      return self.obj[frozenset((idx,))] 

d = dict() 
F = FrozenSetProxy(d) 
F[1,2,3] = 4 
F[1] = 5 
print d 
print F[1] 
+0

Si tratta di un eccessivo po ', non è vero? – delnan

+0

@mgilson: eccellente, anche se sarebbe bello mostrare un esempio del suo utilizzo. –

+0

@delnan - Sort of. Non vedo alcun altro modo per ottenere la sintassi che l'OP sta richiedendo però. – mgilson

4

Non c'è niente come un punto di riferimento in Python C++, e la sintassi da utilizzare è illegale per l'avvio (con le parole di il parser: can't assign to function call). È possibile emularlo con un oggetto o sottoclasse dict per personalizzare il proprio __getitem__. Ma c'è un modo più semplice e meno invasivo: Passare il valore per l'aiutante troppo, e lasciarlo gestire l'assegnazione:

def blah(f): 
    def F(*args, value): 
     f[frozenset(args)] = value 
    F(1, 3, 4, value=5) 
    F(1, value=3) 

Si noti che questo utilizza una funzione di 3 Python, parole chiave solo i parametri. Se avete bisogno di lavorare con Python 2, è possibile emulare la sintassi chiamata accettando **kwdargs:

def F(*args, **kwds): 
    # optional: check that no other keyword arguments were passed 
    f[frozenset(args)] = kwds['value']