2013-01-21 13 views
8

chcę zrobić coś takiego:Alias ​​do pracy w słowniku Pythona

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

ale to tylko bolesne, aby wpisać je cały czas, czy jest tak, aby mieć alias do tego? Wiem, że w C++ jest możliwe, aby mieć funkcję pomocnika, który zwróci referencję więc można po prostu wpisać:

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

F w funkcji pomocnika. Dziękuję bardzo!

Odpowiedz

13

Myślę, że to naprawdę może być osiągnięty tylko przez podklasy:

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 

Wynik:

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

ten wprowadza asymetrię między __getitem__ i __setitem__ które mogłyby być łatwo ustalony przez ponowne zdefiniowanie __getitem__ w ten sam sposób.

Może się to wydawać trochę Messy - Rzeczywiście jest. Dlaczego potrzebna jest podklasa? To sprawia, że ​​trudniej jest umieścić obiekty nie będące obiektami frozenset w słowniku jako klucze. Można łatwo wykorzystać ten przepis, choć utworzyć obiekt proxy, który zrobi to z 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

jest to przesada tad, prawda? – delnan

+0

@mgilson: Doskonały, chociaż dobrze byłoby pokazać przykład jego użycia. –

+0

@delnan - sortowanie. Nie widzę żadnego innego sposobu na uzyskanie składni, której żąda OP. – mgilson

4

nie ma to jak C++ odniesienia w Pythonie, a składnia używasz jest nielegalne, aby uruchomić (w słowach analizator składni: can't assign to function call). Ci mógłby naśladować go z obiektu lub podklasy dict aby dostosować jego __getitem__. Ale jest prostsze i mniej inwazyjne sposób: przekazanie wartości do pomocnika też, i niech sobie zadanie:

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

pamiętać, że ta używa Python 3 funkcję, tylko słowa kluczowe parametry. Jeśli jest to potrzebne do pracy z Pythonem 2, można emulować składnię wywołania akceptując **kwdargs:

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