2012-03-23 9 views
6

Używam niestandardowych obiektów jako kluczy w słowniku Pythona. Obiekty te mają domyślnie zdefiniowane metody hash i eq, które są używane w domyślnym porównaniu Ale w niektórych funkcjach muszę użyć innego sposobu, aby porównać te obiekty. Czy istnieje sposób na zastąpienie lub przekazanie nowego porównywalnika dla tego porównania klucza tylko dla tej konkretnej funkcji.Klucze słownika języka Python (które są obiektami klasy) Porównanie z wieloma porównawczymi

Aktualizacja: Moja klasa ma następujące typu funkcjonalności (tu nie mogę edytować Hash sposób, będzie to miało wpływ na wiele innych miejsc)

class test(object): 

    def __init__(self,name,city): 
     self.name=name 
     self.city=city 

    def __eq__(self,other): 
     hash_equality= (self.name==other.name) 
     if(not hash_equality): 
      #check with lower 
      return (self.name.lower()==other.name.lower()) 


    def __hash__(self): 
     return self.name.__hash__() 

my_dict={} 
a=test("a","city1") 
my_dict[a]="obj1" 
b=test("a","city2") 
print b in my_dict #prints true 
c=test("A","city1") 
print c in my_dict #prints false 
print c in my_dict.keys() #prints true 
# my_dict[c] throw error 

Jest to normalna funkcjonalność. Ale w jednej konkretnej metody chcę zastąpić/lub przekazać nowe niestandardowe porównywarka gdzie nowy kod hash jest jak

def __hash__(self): 
    return self.name.lower().__hash__() 

tak aby c in my_dict powraca tury

lub my_dict[c] will return "obj1"

Niestety tak wiele aktualizacji.

Podobnie jak w przypadku sortowania, możemy przekazać niestandardową metodę porównywania, czy istnieje sposób, aby zrobić to samo tutaj.

+0

Źle odczytałem pytanie (chodziło o sortowanie). Nadal możesz podać kod, aby zilustrować, co próbujesz osiągnąć? –

+0

Potrzebuję jednej konkretnej metody porównywania tylko w jednej funkcji. I przez sortowanie, mam na myśli, że jak w sortowaniu możemy przekazać porównań, można to zrobić podczas sprawdzania kluczy – gsagrawal

+0

Przy okazji, czy jesteś pewien, że chcesz '__eq__'-funkcja do porównywania skrótów? Hashe mogą mieć kolizje, więc w niektórych przypadkach może pojawić się nieoczekiwane zachowanie. –

Odpowiedz

0

teraz używam niestandardowej dict (klasa pochodzi od dict), które biorą porównywarka jako parametr i mam przesłonięte zawiera i getitems(), która sprawdza i podać wartość w oparciu o porównywarkę.

0

Spójrz na comparison methods, który możesz zdefiniować w obiekcie.

W zależności od tego, co chcesz zrobić, może być interesujące także __cmp__.

+0

zaktualizował opis pytania. __cmp__ nie pomaga tutaj – gsagrawal

4

Jedynym sposobem na wykonanie tej pracy jest utworzenie kopii słownika przy użyciu nowej funkcji skrótu i ​​porównania. Powodem jest to, że słownik musi ponownie zaprogramować każdy przechowywany klucz za pomocą nowej funkcji skrótu, aby wyszukiwanie działało tak, jak chcesz. Ponieważ nie możesz podać niestandardowej funkcji skrótu do słownika (zawsze używa ona jednego z obiektów-kluczy), najlepiej jest zawinąć obiekty w typ, który używa niestandardowych funkcji mieszania i porównywania.

class WrapKey(object): 
    __init__(self, wrapee): 
     self._wrapee = wrapee 

    __hash__(self): 
     return self._wrapee.name.lower().__hash__() 

    __eq__(self, other): 
     return self._wrapee.name == other._wrapee.name 


def func(d): 
    d_copy = dict((WrapKey(key), value) for key, value in d.iteritems()) 
    # d_copy will now ignore case 
0

Trochę Hack do tej sytuacji:

class test(object): 

    def __init__(self,name,city,hash_func=None): 
     self.name=name 
     self.city=city 
     self.hash_func = hash_func 

    def __eq__(self,other): 
     return self.__hash__()==other.__hash__() 

    def __hash__(self): 
     if self.hash_func is None: 
      return self.name.__hash__() 
     else: 
      return self.hash_func(self) 

my_dict={} 
a=test("a","city1") 
my_dict[a]="obj1" 
b=test("a","city2") 
print b in my_dict #prints true 
c=test("A","city1") 
print c in my_dict #Prints false 
c.hash_func = lambda x: x.name.lower().__hash__() 
print c in my_dict #Now it prints true 

Nie można zmienić hash przechowywane w dict, ale można zmienić użycie skrótu dla patrząc w górę. Oczywiście, prowadzi to do czegoś dziwne jak to

my_dict={} 
a=test("a","city1") 
my_dict[a]="obj1" 
a.hash_func = lambda x: 1 
for key in my_dict: 
    print key in my_dict # False 
0

Kroki: Zaimplementuj niestandardową klasę kluczy i zastąp funkcję mieszania i równości.

np.

class CustomDictKey(object): 

def __init__(self, 
      param1, 
      param2): 

      self._param1 = param1 
      self._param2 = param2 

# overriding hash and equality function does the trick 

def __hash__(self): 
    return hash((self._param1, 
      self._param2)) 

def __eq__(self, other): 
    return ((self._param1, 
      self._param2) == (other._param1, 
      other._param2)) 

def __str__(self): 
    return "param 1: {0} param 2: {1} ".format(self._param1, self._param2) 

metoda main

if name == 'main': 

    # create custom key 
    k1 = CustomDictKey(10,5) 

    k2 = CustomDictKey (2, 4) 

    dictionary = {} 

    #insert elements in dictionary with custom key 
    dictionary[k1] = 10 
    dictionary[k2] = 20 

    # access dictionary values with custom keys and print values 
    print "key: ", k1, "val :", dictionary[k1] 
    print "key: ", k2, "val :", dictionary[k2] 

Patrz odnośnik Using custom class as key in Python dictionary aby uzyskać szczegółowe informacje.

Powiązane problemy