Ключи словаря Python (которые являются объектами класса) сравнение с множественным компаратором - PullRequest
6 голосов
/ 23 марта 2012

Я использую пользовательские объекты в качестве ключей в словаре Python. Эти объекты имеют определенные методы hash и eq по умолчанию, которые используются при сравнении по умолчанию Но в какой-то функции мне нужно использовать другой способ сравнения этих объектов. Так есть ли способ переопределить или передать новый компаратор для сравнения этих ключей только для этой конкретной функции.

Обновлено: у моего класса есть следующий тип функциональности (здесь я не могу редактировать хэш метод, это сильно повлияет в других местах)

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

Это нормальная функциональность. Но в одном конкретном методе я хочу переопределить / или передать новый пользовательский компаратор, где новый хэш код похож на

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

так что c in my_dict возвращает туру

или my_dict[c] will return "obj1"

Извините за столько обновлений.

Как и при сортировке, мы можем передать пользовательский метод в качестве компаратора, есть ли способ сделать то же самое здесь.

Ответы [ 5 ]

4 голосов
/ 23 марта 2012

Единственный способ сделать эту работу - создать копию вашего словаря с использованием новой хеш-функции и функции сравнения. Причина в том, что словарь должен перефразировать каждый сохраненный ключ с новой хэш-функцией, чтобы поиск работал так, как вы хотите. Поскольку вы не можете предоставить пользовательскую хеш-функцию для словаря (он всегда использует один из ключевых объектов), вам лучше всего обернуть объекты в тип, который использует ваши пользовательские хеш-функции и функции сравнения.

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 голосов
/ 27 мая 2015

Шаги: реализовать пользовательский класс ключей и переопределить хэш и функцию равенства.

например,

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)

основной метод

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]

См. Ссылку Использование пользовательского класса в качестве ключа в словаре Python для получения полной информации.

0 голосов
/ 23 марта 2012

теперь я использую пользовательский dict (производный класс dict), который принимает в качестве параметра сравнение, и я переопределил , содержащий и getitems (), который проверяет и дает значение на основеComparer.

0 голосов
/ 23 марта 2012

Небольшой взлом для этой ситуации:

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

Вы не можете изменить хэш, сохраненный в dict, но вы можете изменить использование хеша для поиска. Конечно, это приводит к чему-то странному, как это

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 голосов
/ 23 марта 2012

Взгляните на методы сравнения , которые вы можете определить в объекте.

В зависимости от того, что вы хотите сделать, __cmp__ также может быть интересным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...