简体   繁体   English

Python字典键(它是类对象)与多个比较器进行比较

[英]Python dictionary keys(which are class objects) comparison with multiple comparer

I am using custom objects as keys in python dictionary. 我在python字典中使用自定义对象作为键。 These objects has some default hash and eq methods defined which are being used in default comparison But in some function i need to use a different way to compare these objects. 这些对象定义了一些默认的hasheq方法,这些方法在默认比较中使用但是在某些函数中我需要使用不同的方法来比较这些对象。 So is there any way to override or pass a new comparer for these key comparison for this specific function only. 那么有没有办法为这个特定的函数覆盖或传递一个新的比较器来进行这些键比较。

Updated: My class has following type of functionality ( here i can not edit hash method ,it will affect a lot at other places) 更新:我的类有以下类型的功能(这里我不能编辑哈希方法,它会在其他地方影响很多)

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

This is the normal functionality. 这是正常的功能。 But in one specific method i want to override/or pass a new custom comparer where the new hash code is like 但是在一个特定的方法中,我想覆盖/或传递一个新的自定义比较器,其中新的哈希代码就像

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

so that c in my_dict returns ture 以便c in my_dict中的c in my_dict返回ture

or my_dict[c] will return "obj1" my_dict[c] will return "obj1"

Sorry for so many updates. 很抱歉这么多的更新。

Like in sorting we can pass custom method as comparer , is there any way to do the same here. 像在排序中我们可以将自定义方法作为比较器传递,有没有办法在这里做同样的事情。

The only way to make this work is to create a copy of your dictionary using the new hash and comparison-function. 使这项工作的唯一方法是使用新的哈希和比较函数创建字典的副本。 The reason is that the dictionary needs to rehash every stored key with the new hash-function to make the lookup work as you desire. 原因是字典需要使用新的哈希函数重新散列每个存储的密钥,以使查找按照您的意愿工作。 Since you cannot provide a custom hash-function to a dictionary (it always uses the one of the key-objects), your best bet is probably to wrap your objects in a type that uses your custom hash and comparison-functions. 由于您无法为字典提供自定义哈希函数(它总是使用其中一个键对象),因此最好的办法是将对象包装在使用自定义哈希和比较函数的类型中。

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

Steps : Implement a custom key class and override hash and equality function. 步骤:实现自定义键类并覆盖哈希和相等函数。

eg 例如

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)

main method 主要方法

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]

Refer the link Using custom class as key in Python dictionary for complete details. 有关完整的详细信息,请参阅链接使用自定义类作为Python字典中的键

Have a look at the comparison methods you can define in an object. 看看您可以在对象中定义的比较方法

Depending on what you want to do, __cmp__ might also be interesting. 根据你想做的事情, __cmp__也可能很有趣。

A little hack for this situation: 这种情况有点破解:

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

You can't change the hash stored in the dict, but you can change the hash use for looking up. 您无法更改存储在dict中的哈希值,但您可以更改哈希用于查找。 Of course, this leads to something weird like this 当然,这会导致像这样的奇怪

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

现在我使用自定义dict(派生类的dict),它将comparer作为参数,我已经覆盖了containsgetitems (),它根据比较器检查和给出值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM